Search code examples
xmlbashopenhab

How to parse a XML file in Bash with multiple same labels


I have read this answer: https://stackoverflow.com/a/7052168/6557127 , but my XML file is a bit different (openHAB REST API):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
 <item>
    <type>GroupItem</type>
    <name>All</name>
    <state>baz</state>
    <link>http://localhost:8080/rest/items/All</link>
 </item>
 <item>
    <type>GroupItem</type>
    <name>foo</name>
    <state>bar</state>
    <link>http://localhost:8080/rest/items/foo</link>
 </item>
</items>

How can I get the state of item foo in bash?


Solution

  • With XMLStarlet:

    xmlstarlet sel -t -m "//item[name='foo']/state" -v .
    

    ...or, with Python 2.7 (here, called from a shell function):

    get_state() {
      python -c '
    import xml.etree.ElementTree as ET
    import sys
    
    doc = ET.parse(sys.stdin)
    el = doc.find(".//item[name=\"%s\"]/state" % (sys.argv[1],))
    if el is not None:
        print el.text
    ' "$@"
    }
    

    ...used as:

    foo_state=$(get_state foo <your.xml)
    

    In either of cases, we're using a real XML parser (rather than trying to hack something together that doesn't really understand the syntax), and leveraging the XPath language to construct our actual query.