XMLLINT 및 BASH를 사용하여 XML 파일의 네임스페이스를 구문 분석하는 방법

XMLLINT 및 BASH를 사용하여 XML 파일의 네임스페이스를 구문 분석하는 방법

다음은 재고 추적을 위한 Adobe XML swidtag의 예입니다. 관련 정보를 구문 분석하고 새 텍스트 파일로 출력하려면 bash에서 xmllint를 사용해야 합니다.

예를 들어 다음을 구문 분석하고 싶습니다.

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

이것을 사용해 보았지만 네임스페이스를 읽을 수 없습니다.

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

나도 시도했다

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

그런데 이런 오류가 발생했어요

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

Creative Suite 5용 샘플 마크업 파일 다음 예는 Adobe Photoshop CS5 일련 번호 Creative Suite 5 Master Collection(제품군)에 대한 것입니다.

<?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>

답변1

이것논의하다매우 계몽적입니다.

이상적이지 않더라도 최소한 다음을 수행할 수 있어야 합니다.

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

또는 사용xmlstarlet대신에:

xmlstarlet sel -t -v //swid:product_version/swid:name file.xml

답변2

여기 문서를 사용해 보세요. 예:

#!/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

xmllint이 매개변수를 지원 하는 이후 버전 에 적용됩니다 --xpath.

답변3

이전 버전 사용xmllint(--xpath는 지원되지 않습니다.) 보다 직관적으로 네임스페이스와 쿼리를 설정할 수 있습니다(그러나 추가 쓰레기를 제거해야 합니다).

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

답변4

Jenkins 쉘 스크립트에서 pom.xml(maven 구성 파일)을 읽는 데 비슷한 문제가 있었습니다. 좋은 결과를 얻으려면 다음과 같이 하세요.

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

XML에 이러한 추가 사항이 있으면 문제가 없는 것 같습니다.

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

xmllint --xpath "//*[local-name()='product_version']/*[local-name()='name']/text()" file.xml작동하지 않습니다

내 경우에는 pom.xml에 "version" 요소가 많았기 때문에 특정 요소를 원한다면 경로가 정확해야 하고, 그렇지 않으면 원하지 않는 값이 여러 개 나올 것이다.

관련 정보