When I am having input.xml
, and want to update it to get output.xml
(see below) XMLSTARLET fails.
First I tried to find the correct XSLT function to get the needed values, which led to this:
xmlstarlet sel -t -m //field -v . -o "=" -v 'substring("ABCDEFGHIJK",position(),1)' -n input.xml
output:
5 =A
3 =B
2 =C
4 =D
55 =E
42 =F
This made me believe that I should be able to update this XML with the following command:
xmlstarlet ed -u //field -x 'substring("ABCDEFGHIJK",position(),1)' input.xmlxmlstarlet ed -u //field -x 'substring("ABCDEFGHIJK",position(),1)' input.xml
But I did get:
Invalid context position
Segmentation fault
I tried using XmlStarlet on Windows 11, and on Ubuntu 20.04, both did a core dump.
I am interested in another solution using XmlStarlet.
FILES
input.xml
<root>
<field> 5 </field>
<field> 3 </field>
<field> 2 </field>
<field> 4 </field>
<field> 55 </field>
<field> 42 </field>
</root>
(desired) output.xml
<root>
<field>A</field>
<field>B</field>
<field>C</field>
<field>D</field>
<field>E</field>
<field>F</field>
</root>
position()
works with xmlstarlet select
's -m (--match)
option (i.e. xsl:for-each
) which determines the context position.
xmlstarlet select --indent -t \
-e '{name(*)}' \
-m '//field' -e '{name()}' -v 'substring("ABCDEFGHIJK",position(),1)' \
file.xml
With xmlstarlet edit
's -u (--update)
you can use a sibling node count, e.g.
xmlstarlet edit -O \
-u '//field' -x 'substring("ABCDEFGHIJK",1+count(preceding-sibling::field),1)' \
file.xml
or
xmlstarlet edit -O \
-u '//field' -x 'substring("ABCDEFGHIJK",count(preceding-sibling::* | self::*),1)' \
file.xml
Each of these commands produces the desired output. Line continuation chars added for readability.