XMLStarlet: Printing one line per item, while using datum from parent element XMLStarlet: Printing one line per item, while using datum from parent element bash bash

XMLStarlet: Printing one line per item, while using datum from parent element


Search for the WaveformData -- given as it's what you want one line per each of -- and just traverse upwards in the tree to find your time element.

$ xmlstarlet sel -T -t -m /XML/Waveforms/WaveformData \     -v ../@Time -o "," \     -v @Channel -o "," \     -v . -n <in.xml01/01/2009 3:00:02 AM,I,1, 2, 3, 4, 5, 6 01/01/2009 3:00:02 AM,II,9, 8, 7, 6, 5, 4 01/01/2009 3:00:04 AM,I,1, 2, 3, 4, 5, 6 01/01/2009 3:00:04 AM,II,9, 8, 7, 6, 5, 4 

Alternately, if you know that each Waveforms will have exactly two WaveformData children, you could do the following:

$ xmlstarlet sel -T -t -m /XML/Waveforms \    -v ./@Time -o ",I,"  -v './WaveformData[@Channel="I"]' -n \    -v ./@Time -o ",II," -v './WaveformData[@Channel="II"]' -n <in.xml01/01/2009 3:00:02 AM,I,1, 2, 3, 4, 5, 601/01/2009 3:00:02 AM,II,9, 8, 7, 6, 5, 401/01/2009 3:00:04 AM,I,1, 2, 3, 4, 5, 601/01/2009 3:00:04 AM,II,9, 8, 7, 6, 5, 4


To give a slight variation of Charles Duffy's answer, you could use the concat() function to simplify it a bit, and an initial template to provide the CSV header:

$ xmlstarlet sel \    -t -o 'Time Attribute, Channel Attribute, Data' -n \    -t -m '//Waveforms/WaveformData' \       -v 'concat(../@Time, ", ", @Channel, ", ", text())' -n \  waveforms.xmlTime Attribute, Channel Attribute, Data01/01/2009 3:00:02 AM, I, 1, 2, 3, 4, 5, 601/01/2009 3:00:02 AM, II, 9, 8, 7, 6, 5, 401/01/2009 3:00:04 AM, I, 1, 2, 3, 4, 5, 601/01/2009 3:00:04 AM, II, 9, 8, 7, 6, 5, 4