Add a document with two main nodes to an existing document using xmlstarlet
I have a existing XML that looks like this:
<data> <item> <A>value1</A> <B>value1<B> </item> <item> <A>value2</A> <B>value2<B> </item> </data>
To this xml file I want to add a second one:
<data> <item> <A>value2</A> <B>value2<B> </item> <item> <A>value3</A> <B>value3<B> </item> </data>
The resulting file should look like this:
<data> <item> <A>value1</A> <B>value1<B> </item> <item> <A>value2</A> <B>value2<B> </item> <item> <A>value3</A> <B>value3<B> </item> <item> <A>value4</A> <B>value4<B> </item> </data>
I use the followig command
xmlstarlet edit --subnode '//data' --type text -n '' --value "$(xmlstarlet select --omit-decl -t --copy-of '//data/item' filename_to_add.xml | xmlstarlet unescape | xmlstarlet format --nsclean)" filename.xml
I get the error
Extra content at the end of the document </item><item>
I guess that is because the xml document in my select query has two main nodes item and that is no valid xml. I understand that, however, it’s just a step within the process of adding it. Unfortunately, it doesn’t allow me to add the subnode. What can I do?
You have your closing bracket at the wrong place. Try this command:
xmlstarlet edit --subnode '//data' --type text -n '' --value "$(xmlstarlet select --omit-decl -t --copy-of '//data/item' filename_to_add.xml.xml)" filename.xml | xmlstarlet unescape | xmlstarlet format --nsclean
In the given example you could change both //data
to /data
simplifying the expressions.
Its output is
<?xml version="1.0"?> <data> <item> <A>value1</A> <B>value1</B> </item> <item> <A>value2</A> <B>value2</B> </item> <item> <A>value2</A> <B>value2</B> </item> <item> <A>value3</A> <B>value3</B> </item> </data>
This is the desired output (your input files and the desired output in your question are out-of-sync).