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>

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

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 '^(/ >| -----)'

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.


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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.