web-dev-qa-db-ja.com

XMLからノード値を抽出するためのネイティブシェルコマンドセット

私はpom.xmlからノードの値を抽出しようとしています:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <parent>
        <groupId>org.me.labs</groupId>
        <artifactId>my-random-project</artifactId>
        <version>1.5.0</version>
    </parent>
    ...
</project>

Shellコマンドを使用して、XMLからartifactIdとversionを抽出する必要があります。次の要件/観察事項があります。

  1. シェルスクリプトは、職場で使用するビルドアセンブリファイル内で実行されるため、スクリプトは小さいほど良いです。
  2. 複数のシステム(通常はRHEL5)で使用されるため、デフォルトのイメージでネイティブに実行できるものを探しています。
  3. このようなタグは、pomの他の場所で発生する可能性があるため、これらのタグを単純にawkすることはできません。

私は次を試しました:

  1. xpath 私のMacでは動作しますが、RHELマシンではデフォルトでは使用できません。同様に、xmllint --xpathについても、xmllintの後のバージョンでのみ利用可能だと思います。
  2. xmllint --pattern 有望に思えましたが、xmllint --pattern '//project/parent/version' pom.xml(XML全体を印刷)またはxmllint --stream --pattern '//project/parent/version' pom.xml(出力なし)から出力を取得できないようです。

私はこれがSOに関する一般的な質問であることを理解していますが、上記の点が私がそれらの答えを使用できない理由です。あなたの助けのためのTIA。

25
Karthik. V

私はしばらくの間、xmllint --Shell

echo "cat //project/parent/version" | xmllint --Shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g'

XMLノードにpom.xmlのような名前空間属性がある場合、物事はより重くなり、基本的に名前でノードを抽出します:

echo "cat //*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']" | xmllint --Shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g'

それが役に立てば幸い。誰もがこれらの表現を簡単にできるなら、私は感謝するでしょう。

14
Karthik. V

--formatは、ドキュメントのフォーマット(インデントなど)にのみ使用されます。 --xpath(Ubuntuでテスト済み、libxml v20900)を使用してこれを行うことができます。

$ xmllint --xpath "//project/parent/version/text()" pom.xml
1.5.0
18
Salem

ウェブサイトから価値を引き出すいい方法を探してここに来ました。次の例は、(ポスターとは異なり)--xpathをサポートするxmllintのバージョンを持っている人に役立ちます。

Elasticsearch .debfileの最新の安定バージョンをプルしてインストールする必要がありました。メンテナーは、クラス「バージョン」のスパンにバージョン番号を役立てています。

version=`curl -s http://www.elasticsearch.org/download/ |\
 xmllint --html --xpath '//span[@class="version"]/text()'\
 2>/dev/null - `;

何が起こっている:

Curl -s(サイレント)オプションを使用します。

curl -s http://www.elasticsearch.org/download/

Xmllint --htmlおよび--xpathスイッチを使用します。 xpath引数(単一引用符内)

'//span[@class="version"]/text()'

...クラス属性(@class) "version"を持つ<span>ノードを探し、テキスト値(/ text())を抽出します。

Xmllintは(サプライズ!)リンターなので、htmlストリーム内の避けられないゴミについて不平を言うでしょう。通常の方法でstderrを/ dev/nullに送ります。

 2>/dev/null

最後に、xmllintコマンドの最後の「-」に注意してください。これは、xmllintにストリームがstdinから来ていることを伝えます。

5
lysdexia

text() XPath関数を使用すると、XMLタグを削除しなくても、要素の値が得られます。

echo "cat //project/parent/version/text()" | xmllint --Shell pom.xml
3
jpwilksch

POMを使用すると、xmllintが期待どおりに動作することを妨げるネームスペースの問題が発生する場合があります。 この記事 は、代替の非常に優れたソリューションを示しています(sed段落をご覧ください)。

0

あなたが試すことができます

xmllint --xpath "/*[name()='project']/*[name()='groupId']/text()" pom.xml

0
Tex