Quantcast
Channel: Generate tree output from specific/general XML file in Bash - Ask Ubuntu
Viewing all articles
Browse latest Browse all 3

Answer by muru for Generate tree output from specific/general XML file in Bash

$
0
0

Adapting one of the examples from the xmlstarlet docs:

xmlstarlet sel -T -t -m '//*' \    -i '@display' \        -m 'ancestor-or-self::*' \            -i '(position()=last())' \                -o '-> ' -v '@display' -b \            -o $'\t' -b \        -n foo.xml

The example is:

Print structure of XML element using xml sel (advanced XPath expressions and xml sel command usage)

xml sel -T -t -m '//*' \-m 'ancestor-or-self::*' -v 'name()' -i 'not(position()=last())' -o . -b -b -n \xml/structure.xml

Result Output:

a1a1.a11a1.a11.a111a1.a11.a111.a1111a1.a11.a112a1.a11.a112.a1121a1.a12a1.a13a1.a13.a131

From here, the things we need to modify are:

  • print the display attribute instead of the name, so @display instead of name()
  • print it only for the last element. We already have the test for printing . for all but the last element, so it's easy to invert that.
  • print tabs to indent (we can do it after every element, it will just leave trailing, invisible tab), so just -o $'\t'. $'\t' in bash will get you a tab character.
  • print only for elements which have the display attribute, so -i '@display'

I have indented the command above to make the flow clearer.

The output I get:

$ xmlstarlet sel -T -t -m '//*' -i '@display' -m 'ancestor-or-self::*' -i '(position()=last())' -o '-> ' -v '@display' -b -o $'\t' -b -n foo.xml-> English    -> Main Menu        -> Broadband            -> Load and Save Profiles                -> Load Profile                -> Save Profile                -> Delete Profile            -> Interface                -> xDSL                -> SFP                -> Ethernet                -> SHDSL            -> xDSL Interface                -> xDSL Mode                    -> Annex A/M                    -> Annex B/J                -> MAC Address                    -> MAC Address                -> Vectoring Mode                    -> Disabled                    -> Enabled                    -> Friendly                -> G.FAST                    -> Disabled                    -> Enabled

After thinking a bit, the following is simpler:

xmlstarlet sel -T -t -m '//*' \    -i '@display' \        -m 'ancestor::*' \            -o $'\t' -b \        -o '-> ' -v '@display' -n foo.xml

Using ancestor::* instead of ancestor-or-self::* makes printing the tabs correctly easier, and eliminates the extra test for last element.

Similar output, but without trailing tabs:

-> English    -> Main Menu        -> Broadband            -> Load and Save Profiles                -> Load Profile                -> Save Profile                -> Delete Profile            -> Interface                -> xDSL                -> SFP                -> Ethernet                -> SHDSL            -> xDSL Interface                -> xDSL Mode                    -> Annex A/M                    -> Annex B/J                -> MAC Address                    -> MAC Address                -> Vectoring Mode                    -> Disabled                    -> Enabled                    -> Friendly                -> G.FAST                    -> Disabled                    -> Enabled

Viewing all articles
Browse latest Browse all 3

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>