Fetching multiple values using xmllint
Asked Answered
S

2

11

I'd like to use xpath from xmllint to fetch a hostname and a serial number.

Here is the XML

<hosts>
 <host name="blah001" serial="ABC001">
  <moreinfo />
 </host>
 <host name="blah002" serial="ABC002">
  <moreinfo />
 </host>
 ..
</hosts>

I can fetch all serials with host name blah*:

/ > cat //hosts/host[starts-with(@name,"blah")]/@serial
 -------
 serial="ABC001"
 -------
 serial="ABC002"

But I also want to see which hostname had that serial. Is that possible?

Subalternate answered 12/2, 2015 at 15:25 Comment(1)
unix.stackexchange.com/questions/52711/…Aboulia
D
6

Perhaps it would suffice to simply select all attributes of the host element?

$ xmllint example.xml --xpath "//hosts/host[starts-with(@name,"blah")]/@*" > out.txt
$ cat out.txt
  name="blah001" serial="ABC001" name="blah002" serial="ABC002"

If that's not enough - if the output should be structured in a certain way, I'd recommend you write a simple XSLT transformation or use XQuery.

EDIT

so I will follow your suggestion and use xslt or xquery

Good, in case you decide for XSLT, the stylesheet you need would look similar to:

XSLT Stylesheet (1.0)

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" encoding="UTF-8" />

    <xsl:template match="host[starts-with(@name,'blah')]">
        <xsl:value-of select="concat('HOST: ',@name, ' SERIAL: ', @serial)"/>
    </xsl:template>
</xsl:transform>

Output

 HOST: blah001 SERIAL: ABC001
 HOST: blah002 SERIAL: ABC002
Disaster answered 12/2, 2015 at 15:31 Comment(1)
That would give me all matches on a single line though, so I will follow your suggestion and use xslt or xquery.Subalternate
S
7

This can be done in xmllint with following XPath expression. Let suppose your XML is named hosts.xml.

xmllint hosts.xml --xpath '//host[starts-with(@name,"blah")]/@name | //host[starts-with(@name,"blah")]/@serial' | xargs -n2

This is because the | operator in an XPath expression can support several paths.

Sarena answered 22/3, 2018 at 8:35 Comment(0)
D
6

Perhaps it would suffice to simply select all attributes of the host element?

$ xmllint example.xml --xpath "//hosts/host[starts-with(@name,"blah")]/@*" > out.txt
$ cat out.txt
  name="blah001" serial="ABC001" name="blah002" serial="ABC002"

If that's not enough - if the output should be structured in a certain way, I'd recommend you write a simple XSLT transformation or use XQuery.

EDIT

so I will follow your suggestion and use xslt or xquery

Good, in case you decide for XSLT, the stylesheet you need would look similar to:

XSLT Stylesheet (1.0)

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" encoding="UTF-8" />

    <xsl:template match="host[starts-with(@name,'blah')]">
        <xsl:value-of select="concat('HOST: ',@name, ' SERIAL: ', @serial)"/>
    </xsl:template>
</xsl:transform>

Output

 HOST: blah001 SERIAL: ABC001
 HOST: blah002 SERIAL: ABC002
Disaster answered 12/2, 2015 at 15:31 Comment(1)
That would give me all matches on a single line though, so I will follow your suggestion and use xslt or xquery.Subalternate

© 2022 - 2024 — McMap. All rights reserved.