Search code examples
xmlxmlstarletxmlupdate

Updating two xml file using xmlstarlet


I have some issue to update an xml file with the data of a second xml file using xmlstarlet. For exemple i have a first xml file of this type :

<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <timestamp></timestamp>
  <results>
    <idFile>1</dFile>
    <activated>true</activated>
    <id>9159820</id>
    <content>
      <resultDate>25/02/2018 19:33</resultDate>
      <presDate>01/01/2018</prescriptionDate>
      <seen>false</seen>
      <prescriberName>BABA</prescriberName>
      <labId>789</labId>
      <labName>Bio</laName>
      <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
          <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
    </content>
  </results>
</root>

And a second file

<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <timestamp></timestamp>
  <results>
    <idFile>2</dFile>
    <activated>true</activated>
    <id>9159810</id>
    <content>
      <resultDate>25/02/2018 19:33</resultDate>
      <presDate>01/01/2018</prescriptionDate>
      <seen>false</seen>
      <prescriberName>BABA</prescriberName>
      <labId>789</labId>
      <labName>Bio</laName>
      <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
          <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
    </content>
  </results>
</root>

And what I would like to have is something like that ( I only need to update ( add) the first file with the element result of the second file) :

<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <timestamp></timestamp>
  <results>
    <idFile>1</dFile>
    <activated>true</activated>
    <id>9159810</id>
    <content>
      <resultDate>25/02/2018 19:33</resultDate>
      <presDate>01/01/2018</prescriptionDate>
      <seen>false</seen>
      <prescriberName>BABA</prescriberName>
      <labId>789</labId>
      <labName>Bio</laName>
      <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
          <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
    </content>
  </results>
  <results>
    <idFile>2</dFile>
    <activated>true</activated>
    <id>9159810</id>
    <content>
      <resultDate>25/02/2018 19:33</resultDate>
      <presDate>01/01/2018</prescriptionDate>
      <seen>false</seen>
      <prescriberName>BABA</prescriberName>
      <labId>789</labId>
      <labName>Bio</laName>
      <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
          <checkedResults>
        <id>177331580</id>
        <localCode>GLU</localCode>
        <localLabel>GLU</localLabel>
        <Code>17856-6</Code>
        <value>IN</value>
        <unit>%</unit>
        <normalLow>4.0</normalLow>
        <normalHeight>6.0</normalHeight>
        <Label>BABA</Label>
      </checkedResults>
    </content>
  </results>
</root>

What I have tried so far :

Use the command xmlstarlet ed 1.xml 2.xml > 3.xml But this command only merge the two files into one with the same header. Do you have any idea to guide me on this issue ?


Solution

  • Append two XML files to each other.

    file1.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <root>
      <timestamp></timestamp>
      <results>
        <idFile>1</idFile>
        <activated>true</activated>
      </results>
    </root>
    

    file2.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <root>
      <timestamp></timestamp>
      <results>
        <idFile>2</idFile>
        <activated>true</activated>
      </results>
    </root>
    

    With xmlstarlet:

    hull=$(xmlstarlet edit --delete '//root/results' file1.xml)
    core1=$(xmlstarlet select --template -c '//root/results/*' file1.xml)
    core2=$(xmlstarlet select --template -c '//root/results/*' file2.xml)
    
    echo "$hull" \
      | xmlstarlet edit --subnode '//root' --type elem -n "results" --value "$core1" \
      | xmlstarlet edit --subnode '//root' --type elem -n "results" --value "$core2" \
      | xmlstarlet unescape \
      | xmlstarlet format
    

    Output:

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <timestamp/>
      <results>
        <idFile>1</idFile>
        <activated>true</activated>
      </results>
      <results>
        <idFile>2</idFile>
        <activated>true</activated>
      </results>
    </root>
    

    See: xmlstarlet, xmlstarlet edit and xmlstarlet select