Wie analysiere ich Namespaces aus einer XML-Datei mit XMLLINT und BASH?

7

Unten habe ich ein Beispiel für einen Adobe XML-Swidtag, mit dem das Inventar verfolgt wird. Ich muss relevante Informationen mit xmllint in bash analysieren und diese in eine neue Textdatei ausgeben.

Zum Beispiel möchte ich Folgendes analysieren

swid:entitlement_required_indicator
swid:product_title
swid:product_version
swid:name
swid:numeric
swid:major
swid:minor
swid:build
swid:review

Ich habe versucht, dies zu verwenden, aber ich kann den Namespace nicht lesen

xmllint --xpath '//swid:product_version/swid:name/text()' file.xml

Ich habe es auch versucht

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

Habe aber diese Fehler

xmlXPathCompOpEval: function local-nameame1 not found
XPath error : Unregistered function
XPath error : Stack usage errror
XPath evaluation failure

Beispiel-Tag-Datei für Creative Suite 5 Das folgende Beispiel bezieht sich auf Adobe Photoshop CS5, das als Creative Suite 5 Master Collection (Suite) serialisiert wurde.

<?xml version="1.0" encoding="utf-8"?>
<swid:software_identification_tag xsi:schemaLocation="http://standards.iso.org/iso/19770/-2/2008/schema.xsd software_identification_tag.xsd" 
     xmlns:swid="http://standards.iso.org/iso/19770/-2/2008/schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<!--Mandatory Identity elements -->
<swid:entitlement_required_indicator>true</swid:entitlement_required_indicator>
<swid:product_title>Acrobat XI Pro</swid:product_title>
<swid:product_version>
    <swid:name>1.0</swid:name>
    <swid:numeric>
        <swid:major>1</swid:major>
        <swid:minor>0</swid:minor>
        <swid:build>0</swid:build>
        <swid:review>0</swid:review>
    </swid:numeric>
</swid:product_version>
<swid:software_creator>
    <swid:name>Adobe Systems Incorporated</swid:name>
    <swid:regid>regid.1986-12.com.adobe</swid:regid>
</swid:software_creator>
<swid:software_licensor>
    <swid:name>Adobe Systems Incorporated</swid:name>
    <swid:regid>regid.1986-12.com.adobe</swid:regid>
</swid:software_licensor>
<swid:software_id>
    <swid:unique_id>CreativeCloud-CS6-Mac-GM-MUL</swid:unique_id>
    <swid:tag_creator_regid>regid.1986-12.com.adobe</swid:tag_creator_regid>
</swid:software_id>

<swid:tag_creator>
    <swid:name>Adobe Systems Incorporated</swid:name>
    <swid:regid>regid.1986-12.com.adobe</swid:regid>
</swid:tag_creator>
<!--Optional Identity elements -->
<swid:license_linkage>
    <swid:activation_status>activated</swid:activation_status>
    <swid:channel_type>SUBSCRIPTION</swid:channel_type>
    <swid:customer_type>RETAIL</swid:customer_type>
</swid:license_linkage>
<swid:serial_number>909702426602037824854600</swid:serial_number>
</swid:software_identification_tag>
Macman
quelle

Antworten:

13

Diese Diskussion ist aufschlussreich.

Zumindest, auch wenn es nicht ideal ist, sollten Sie in der Lage sein:

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

Oder verwenden Sie stattdessen xmlstarlet :

xmlstarlet sel -t -v //swid:product_version/swid:name file.xml
Stéphane Chazelas
quelle
Die Diskussion, die Sie aufgelistet haben, ist sehr aufschlussreich, danke. Denn "// * [local-name () = 'product_version'] ist ein lokaler Name, den ich erstelle? Bsp." // * [name1 () = 'product_version']. Ich habe versucht, es
umzubenennen
2

Mit einer älteren Version von xmllint (die --xpath nicht unterstützt) können Sie einen Namespace festlegen und so intuitiver abfragen (aber Sie müssen zusätzlichen Müll heraussuchen):

#!/bin/bash
echo 'setns swid=http://standards.iso.org/iso/19770/-2/2008/schema.xsd
      cat //swid:product_version/swid:name/text()' | \
xmllint --shell file.xml | egrep -v '^(/ >| -----)'
Ed Randall
quelle
schön und klar. habe in meiner Antwort unten einen ähnlichen Ansatz verwendet.
Roblogic
2

Versuchen Sie es mit einem Here-Doc. Beispiel:

#!/bin/bash
xmllint --shell file.xml <<EOF
setns swid=http://standards.iso.org/iso/19770/-2/2008/schema.xsd
xpath //swid:product_version/swid:name/text()
EOF

Funktioniert mit späteren Versionen xmllint, die den --xpathParameter unterstützen.

Roblogik
quelle
1

Ich hatte ähnliche Probleme beim Lesen von pom.xml (einer Maven-Konfigurationsdatei) im Shell-Skript für Jenkins. Um ein gutes Ergebnis zu erzielen, würde ich Folgendes tun:

xmllint --xpath "//swid:software_identification_tag/*[local-name()='product_version']/*[local-name()='name']/text()" file.xml

Sie scheinen das Problem hier nicht zu haben, wenn Ihre XML diese Art von zusätzlichem Inhalt hat:

<swid:product_specifics>
<swid:product_version>
...
</swid:product_version>
</swid:product_specifics>

xmllint --xpath "//*[local-name()='product_version']/*[local-name()='name']/text()" file.xml wird nicht funktionieren

In meiner Situation enthält eine pom.xml viele "Versions" -Elemente. Wenn Sie also ein bestimmtes Element möchten, sollte der Pfad genau sein, da Sie sonst mehrere Werte erhalten, die Sie nicht möchten.

Sebastien Denis
quelle