XMLコマンドライン処理に相当するGrepおよびSed


147

シェルスクリプトを実行する場合、通常、データはcsvのような単一行レコードのファイルになります。grepおよびを使用してこのデータを処理するのは非常に簡単sedです。しかし、私は頻繁にXMLを扱わなければならないので、コマンドラインを介してそのXMLデータへのアクセスをスクリプト化する方法が本当に必要です。最高のツールは何ですか?


回答:


105

私はxmlstarletがこの種の点でかなり優れていることを発見しました。

http://xmlstar.sourceforge.net/

ほとんどのディストリビューションリポジトリでも利用できるはずです。入門チュートリアルはここにあります:

http://www.ibm.com/developerworks/library/x-starlet.html


1
SourceforgeサイトではWindowsバイナリが利用できることを指摘しておきたいと思います。
Steve Bennett

ただし、私が知る限り、XQueryはサポートされていません。
スティーブベネット

@SteveBennettは確かにそうではありませんが、生のXPathの上に追加する機能は、「grep and sed」と競合するのに十分です。XQueryのファンシーでファンシーな良さを望むなら、まあ、それはperlやawkに相当するXMLに似ています。:)
Charles Duffy

36

いくつかの有望なツール:

  • nokogiri:XPath&CSSセレクターを使用してルビーでHTML / XML DOMを解析する

  • hpricot:非推奨

  • fxgrep:独自のXPathに似た構文を使用してドキュメントをクエリします。SMLで記述されているため、インストールが難しい場合があります。

  • LT XML:SGMLツールから得られるXMLツールキット、を含むsggrepsgsortxmlnormなどがあります。独自のクエリ構文を使用します。ドキュメントは 非常に正式です。Cで記述されています。LTXML 2は、XPath、XInclude、およびその他のW3C標準のサポートを主張しています。

  • xmlgrep2:XPathを使用したシンプルで強力な検索。XML :: LibXMLおよびlibxml2を使用してPerlで記述されています。

  • XQSharp:XPathの拡張であるXQueryをサポートします。.NET Framework用に作成。

  • xml-coreutils:GNU coreutilsに相当するLaird Breyerのツールキット。理想的なツールキットに何を含めるべきかについての興味深いエッセイで議論されました。

  • xmldiff:2つのxmlファイルを比較するためのシンプルなツール。

  • xmltk:debian、ubuntu、fedora、またはmacportsにパッケージがないようで、2007年以降のリリースはなく、移植性のないビルドオートメーションを使用しています。

xml-coreutilsは、ドキュメント化され、最もUNIX指向であるようです。


1
Rubyプログラムのラッパースクリプトを作成し、スクリプトの引数の配列をhpricotに渡せませんか?たとえば、PHPシェルスクリプトでは、次のようなものが機能します。<?php / path / to / hpricot $ argv?>
alastairs

25

Joseph Holstenの優れたリストに、PerlライブラリXML :: XPathに付属するxpathコマンドラインスクリプトを追加します。XMLファイルから情報を抽出する優れた方法:

 xpath -q -e '/entry[@xml:lang="fr"]' *xml

3
これはデフォルトでosxにインストールされますが、-q -eオプションはありません。:例は、「AndroidManifest.xmlに」の「マニフェスト」ノードから属性「パッケージ」の値を取得xpath AndroidManifest.xml 'string(/manifest/@package)' 2> /dev/null
antonj

25

ペアもxml2あり2xmlます。通常の文字列編集ツールでXMLを処理できるようになります。

例。q.xml:

<?xml version="1.0"?>
<foo>
    text
    more text
    <textnode>ddd</textnode><textnode a="bv">dsss</textnode>
    <![CDATA[ asfdasdsa <foo> sdfsdfdsf <bar> ]]>
</foo>

xml2 < q.xml

/foo=
/foo=   text
/foo=   more text
/foo=   
/foo/textnode=ddd
/foo/textnode
/foo/textnode/@a=bv
/foo/textnode=dsss
/foo=
/foo=    asfdasdsa <foo> sdfsdfdsf <bar> 
/foo=

xml2 < q.xml | grep textnode | sed 's!/foo!/bar/baz!' | 2xml

<bar><baz><textnode>ddd</textnode><textnode a="bv">dsss</textnode></baz></bar>

PS html2/ もあります2html


@ジョセフホルステンはい。XPathのことを考えなくてもXMLでハッキングすることができます。
Vi。

いいね!私は中間形式を使用しないツールに焦点を当てていましたが、xmlの高忠実でライン指向の表現のアイデアは、実際のgrepとsedを使い続けるための優れた方法のようです。pyxieを試しましたか?どのように比較しますか?他のライン指向の表現?これを単にxml改行をエンティティ(&#10;)で置き換えるよりも良いと思いますか?これにより、少なくとも同じ行にレコードを貼り付けることができます。投稿を編集して、プロジェクトへのリンクを含めてもらえますか?
ジョセフ・ホルステン

@Joseph Holstenいいえ、pyxie形式がxml2形式よりも役立つとは思いません。xml2はネストされたXML要素に「完全パス」を提供するため、より行指向のマッチングと置換が可能になります。また2xml、部分的な(フィルタリングされた)xml2出力からXMLを簡単に再作成できます。
Vi。

5
+1十分に賛成できない... cat foo.xml | xml2 | grep /bar | 2xml—元の構造と同じですが、「棒」要素を除くすべての要素が削除されています。驚くばかり。
mogsie 2013年

14

xmllintを使用できます。

xmllint --xpath //title books.xml

ほとんどのディストリビューションにバンドルする必要があり、Cygwinにもバンドルされています。

$ xmllint --version
xmllint: using libxml version 20900

見る:

$ xmllint
Usage : xmllint [options] XMLfiles ...
        Parse the XML files and output the result of the parsing
        --version : display the version of the XML library used
        --debug : dump a debug tree of the in-memory document
        ...
        --schematron schema : do validation against a schematron
        --sax1: use the old SAX1 interfaces for processing
        --sax: do not build a tree but work just at the SAX level
        --oldxml10: use XML-1.0 parsing rules before the 5th edition
        --xpath expr: evaluate the XPath expression, inply --noout

2
--xpath引数はありませんxmllintmanpagez.com/man/1/xmllint
Miserable Variable

1
@MiserableVariable:manページが正しくありません。私は自分のバージョンのmanページを見ただけです。xpath引数はリストされていません。これはドキュメントのエラーです。代わりにプログラムを実行してみてください。
Dave Jarvis

2
@MiserableVariable --xpathはごく最近追加されたもので、たとえばRHEL 6バージョンのにはありませんxmllint
Daniel Beck

2
より正確にxmllint --xpathは、libxml2 2.7.7(2010年)で導入されました。
marbu 2014年

9

Windowsでソリューションを探している場合、PowershellにはXMLの読み取りと書き込みのための組み込み機能があります。

test.xml:

<root>
  <one>I like applesauce</one>
  <two>You sure bet I do!</two>
</root>

PowerShellスクリプト:

# load XML file into local variable and cast as XML type.
$doc = [xml](Get-Content ./test.xml)

$doc.root.one                                   #echoes "I like applesauce"
$doc.root.one = "Who doesn't like applesauce?"  #replace inner text of <one> node

# create new node...
$newNode = $doc.CreateElement("three")
$newNode.set_InnerText("And don't you forget it!")

# ...and position it in the hierarchy
$doc.root.AppendChild($newNode)

# write results to disk
$doc.save("./testNew.xml")

testNew.xml:

<root>
  <one>Who likes applesauce?</one>
  <two>You sure bet I do!</two>
  <three>And don't you forget it!</three>
</root>

ソース:https : //serverfault.com/questions/26976/update-xml-from-the-command-line-windows


Powershellに頼る前に、さまざまなLinuxツールと数時間戦いました。これがとても難しいことに驚いています-通常、Linuxのcmd-lineは本当に良いのですが、ここに穴があるようです。注:私の使用例は次のとおりです:1)xpathでノードを見つけ、2)見つかった場合は削除します。3)新しいノードを追加します。4)ファイルを保存します。たくさんのsolr設定を更新していました。これを行う簡単で信頼性の高い方法を誰かが知っているなら、私はすべて耳にした
リチャードハウアー

うわー、これは実際に許容可能なソリューションのラインまでつま先です。しかし、正直なところ、私はおそらくそれはのように見えた場合はそれを受け入れるだろうxps $doc .root.one xps $doc 'AppendChild("three")'xps $doc '.three.set_InnerText("And don't you forget it!")'明らかに劣っています、!
ジョセフホルステン


6

何をしたいかによります。

XSLTが良い方法かもしれませんが、学習曲線があります。xsltprocを試してみて、パラメーターを渡すことができることに注意してください。




3

XQueryは良いソリューションかもしれません。これは(比較的)習得が容易で、W3C標準です。

コマンドラインプロセッサにはXQSharpをお勧めします。


1
BaseXには、(データベースモードに加えて)コマンドラインXQueryプロセッサもあり、標準の最新バージョン(XQuery 3.0の進化するドラフトに非常に厳密に従っています)で最新の状態を保ちます。
Charles Duffy

3

私は最初にxmlstarletを使用し、それをまだ使用しています。クエリが困難になったら、XMLのxpath2およびxquery機能のサポートが必要です。xidelhttp : //www.videlibri.de/xidel.html使用します。


1

同等のGrep

python3コードをラップする「xp」(「xpath」)などのbash関数を定義できます。それを使用するには、python3とpython-lxmlをインストールする必要があります。利点:

  1. たとえばxmllintにない正規表現一致。
  2. コマンドラインで(パイプ内の)フィルターとして使用する

次のように使用するのは簡単で強力です。

xmldoc=$(cat <<EOF
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
EOF
)
selection='//*[namespace-uri()="http://www.sample.com/" and local-name()="job" and re:test(.,"^pro.*ing$")]/text()'
echo "$xmldoc" | xp "$selection"
# prints programming

xp()は次のようになります。

xp()
{ 
local selection="$1";
local xmldoc;
if ! [[ -t 0 ]]; then
    read -rd '' xmldoc;
else
    xmldoc="$2";
fi;
python3 <(printf '%b' "from lxml.html import tostring\nfrom lxml import etree\nfrom sys import stdin\nregexpNS = \"http://exslt.org/regular-expressions\"\ntree = etree.parse(stdin)\nfor e in tree.xpath('""$selection""', namespaces={'re':regexpNS}):\n  if isinstance(e, str):\n    print(e)\n  else:\n    print(tostring(e).decode('UTF-8'))") <<< "$xmldoc"
}

同等のSed

jqの「プログラミング言語」を最大限に活用できるxqの使用を検討してください。python-pipがインストールされている場合は、xqをpip install yqでインストールできます。次の例では、「Keep Accounts」を「Keep Accounts 2」に置き換えます。

xmldoc=$(cat <<'EOF'
<resources>
    <string name="app_name">Keep Accounts</string>
    <string name="login">"login"</string>
    <string name="login_password">"password:"</string>
    <string name="login_account_hint">input to login</string>
    <string name="login_password_hint">input your password</string>
    <string name="login_fail">login failed</string>
</resources>
EOF
)
echo "$xmldoc" | xq '.resources.string = ([.resources.string[]|select(."#text" == "Keep Accounts") ."#text" = "Keep Accounts 2"])' -x

-1

JEdi​​tには、XMLドキュメントのクエリ機能を提供する「XQuery」と呼ばれるプラグインがあります。

コマンドラインではありませんが、動作します!


JEdi​​tはファイルを検索する方法を持っている可能性が高いですが、それが競合相手になることはありませんgrep(1)
ジョセフホルステン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.