Search code examples
xmlxpathxmllint

Returning string from xmllint/xpath


I have the following xml excerpt and what I want is just the string 2014.4.0.0008 in the Version tag.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExternalMetadataPack xmlns="xmlns://www.fortifysoftware.com/schema/externalMetadata" schemaVersion="1.0">
    <PackInfo>
        <Name>Main External List Mappings</Name>
        <PackID>main-external-mappings</PackID>
        <Version>2014.4.0.0008</Version>
    </PackInfo>
</ExternalMetadataPack>

I've tried a few things and gotten as far as this:

xmllint --xpath "//PackInfo/@Version[local-name()='ExternalMetadataPack']" externalmetadata.xml

But nothing seems to be working. This says that the XPath set is empty and if I include string() in the --xpath parameter then it just doesn't return anything.


Solution

  • Try this (ignoring the NS) :

    xmllint --xpath '//*[local-name()="Version"]/text()' file.xml
    

    AFAIK, it's not possible to set a default NS with the --xpath switch, so with the --shell one :

    $ xmllint --shell file.xml <<EOF
    setns x=xmlns://www.fortifysoftware.com/schema/externalMetadata
    cat //x:Version/text()
    EOF
    
    / > setns x=xmlns://www.fortifysoftware.com/schema/externalMetadata
    / > cat //x:Version/text()
     -------
    2014.4.0.0008
    / >
    

    But sadly, there's rubbish in the output, so :

    $ xmllint --shell file.xml <<EOF | grep -Ev '^(/ *>| --+)'
    setns x=xmlns://www.fortifysoftware.com/schema/externalMetadata
    cat //x:Version/text()
    EOF
    

    OUTPUT:

    2014.4.0.0008
    

    Another way :

    xmllint --xpath '//*[namespace-uri()="xmlns://www.fortifysoftware.com/schema/externalMetadata" and local-name()="Version"]/text()' file.xml
    

    Finally is quite more advanced and it seems the proper tool here :

    xml sel -N x="xmlns://www.fortifysoftware.com/schema/externalMetadata" -t -m "//x:Version/text()" -c . -n file.xml
    

    And bonus (avaibility to use XPath 3) saxon-lint

    saxon-lint --xpath 'declare default element namespace "xmlns://www.fortifysoftware.com/schema/externalMetadata";//Version/text()' file.xml