I am very, very, very confused with xmllint. Are there better alternatives? Is there a better way to learn about it than the man page?
How come these two commands work separately, but fail when I combine them?
xmllint --format test.txt --xpath "//*[name()='model']/@mh | //*[name()='instance']/@value" | sed -E -e 's/\s /\n/g'
xmllint --format test.txt --xpath '//*[@id="0x1006e"]/text()'
Combined:
xmllint --format /opt/spectrum/custom/test.txt --xpath "//*[name()='model']/@mh | '//*[@id="0x1006e"]/text()' | //*[name()='instance']/@value" | sed -E -e 's/\s /\n/g'
I also understand it is frowned upon to use sed with XML, but the format option does not work at all when I extract info. XML is really confusing me.
My ultimate goal is to go from this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model-response-list xmlns="http://null" total-models="1" throttle="1" error="EndOfResults">
<model-responses>
<model mh="NULL1">
<attribute id="0x1006e">NULL2</attribute>
<attribute-list id="NULL3">
<instance oid="1" value="Vlan1"/>
<instance oid="10001" value="FastEthernet1/0/1"/>
<instance oid="10002" value="FastEthernet1/0/2"/>
<instance oid="10003" value="FastEthernet1/0/3"/>
<instance oid="10004" value="FastEthernet1/0/4"/>
<instance oid="10005" value="FastEthernet1/0/5"/>
<instance oid="10006" value="FastEthernet1/0/6"/>
<instance oid="10007" value="FastEthernet1/0/7"/>
<instance oid="10008" value="FastEthernet1/0/8"/>
</attribute-list>
</model>
</model-responses>
</model-response-list>
to this:
mh="NULL1"
NULL2
Vlan1
FastEthernet1/0/1
FastEthernet1/0/2
FastEthernet1/0/3
FastEthernet1/0/4
FastEthernet1/0/5
FastEthernet1/0/6
FastEthernet1/0/7
FastEthernet1/0/8
Please help me to XML :'(
CodePudding user response:
There's mixed quoting on the combined XPath expression. Fixing it makes the command work
xmllint --format tmp.xml --xpath "//*[name()='model']/@mh | //*[@id='0x1006e']/text() | //*[name()='instance']/@value" | sed -E -e 's/\s /\n/g'
Result
mh="NULL1"
NULL2
value="Vlan1"
value="FastEthernet1/0/1"
value="FastEthernet1/0/2"
value="FastEthernet1/0/3"
value="FastEthernet1/0/4"
value="FastEthernet1/0/5"
value="FastEthernet1/0/6"
value="FastEthernet1/0/7"
value="FastEthernet1/0/8"
CodePudding user response:
A different approach might be to use an xslt transform to generate the output you are seeking:
xslt file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="//@mh" />
<xsl:apply-templates match="attribute" />
<xsl:text>
</xsl:text>
<xsl:apply-templates select="//@value" />
</xsl:template>
<xsl:template match="@mh">
<xsl:value-of select="concat('mh="', ., '" 
')"/>
</xsl:template>
<xsl:template match="@value">
<xsl:value-of select="concat(., '
')"/>
</xsl:template>
</xsl:stylesheet>
xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model-response-list xmlns="http://null" total-models="1" throttle="1" error="EndOfResults">
<model-responses>
<model mh="NULL1">
<attribute id="0x1006e">NULL2</attribute>
<attribute-list id="NULL3">
<instance oid="1" value="Vlan1"/>
<instance oid="10001" value="FastEthernet1/0/1"/>
<instance oid="10002" value="FastEthernet1/0/2"/>
<instance oid="10003" value="FastEthernet1/0/3"/>
<instance oid="10004" value="FastEthernet1/0/4"/>
<instance oid="10005" value="FastEthernet1/0/5"/>
<instance oid="10006" value="FastEthernet1/0/6"/>
<instance oid="10007" value="FastEthernet1/0/7"/>
<instance oid="10008" value="FastEthernet1/0/8"/>
</attribute-list>
</model>
</model-responses>
</model-response-list>
Output from transform:
$ xsltproc sample.xslt sample.xml
mh="NULL1"
NULL2
Vlan1
FastEthernet1/0/1
FastEthernet1/0/2
FastEthernet1/0/3
FastEthernet1/0/4
FastEthernet1/0/5
FastEthernet1/0/6
FastEthernet1/0/7
FastEthernet1/0/8