I'm trying to use XMLstarlet
to convert some data from XML format to CSV. My data is formatted as
<!-- mydata.xml -->
<alldata>
<data id="first">
<coord><x>0</x><y>5</y></coord>
<coord><x>1</x><y>4</y></coord>
<coord><x>2</x><y>3</y></coord>
</data>
<data id="second">
<coord><x>3</x><y>2</y></coord>
<coord><x>4</x><y>1</y></coord>
<coord><x>5</x><y>0</y></coord>
</data>
</alldata>
I would like to format this data in three columns "id", "x", and "y" to get:
first;0;5
first;1;4
first;2;3
second;3;2
second;4;1
second;5;0
My attempts with XMLstarlet
has failed indicating that I don't really understand what I am doing.
xml sel -T -t -m /alldata/data -v "@id" -m /alldata/data/coord -v "concat(x,';',y)" -n mydata.xml
gives me:
first0;5
1;4
2;3
3;2
4;1
5;0
second0;5
1;4
2;3
3;2
4;1
5;0
which is not what I want or expected. Is it possible to modify my query to get the desired output?
-m /alldata/data -v "@id" -m /alldata/data/coord -v "concat(x,';',y)"
The main problem is the -m /alldata/data/coord
: this matches all the coord
elements in the entire document, what you really wanted was just the coord
under the current data
elements:
-m /alldata/data -v "@id" -m coord -v "concat(x,';',y)"
You also want the id
on every line so you need to move into the inner loop:
-m /alldata/data -m coord -v "concat(../@id,';',x,';',y)"
At this point there is no benefit to having 2 nested loops so we can simplify:
xml sel -T -t -m /alldata/data/coord -v "concat(../@id,';',x,';',y)" -n mydata.xml