UbuntuやCentOS向けに、foo //element@attribute filename.xml
やfoo //element@attribute < filename.xml
などのXPathワンライナーを実行し、結果を1行ずつ返すことができるコマンドラインツールを備えたパッケージがありますか?
私はちょうどapt-get install foo
またはyum install foo
にできるものを探していて、すぐに動作し、ラッパーや他の適応は必要ありません。
近づいてくるものの例を次に示します。
のこぎり。このラッパーを作成すると、上記の方法でラッパーを呼び出すことができます。
#!/usr/bin/Ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML :: XPath。このラッパーで動作します:
#!/usr/bin/Perl
use strict;
use warnings;
use XML::XPath;
my $root = XML::XPath->new(ioref => 'STDIN');
for my $node ($root->find($ARGV[0])->get_nodelist) {
print($node->getData, "\n");
}
XML :: XPathからのxpath
は、-- NODE --
およびattribute = "value"
という非常に多くのノイズを返します。
XML :: Twigのxml_grep
は、要素を返さない式を処理できないため、さらに処理することなく属性値を抽出するために使用することはできません。
編集:
echo cat //element/@attribute | xmllint --Shell filename.xml
は、xpath
と同様のノイズを返します。
xmllint --xpath //element/@attribute filename.xml
はattribute = "value"
を返します。
xmllint --xpath 'string(//element/@attribute)' filename.xml
は、最初に一致した場合にのみ、必要なものを返します。
ほぼ問題を解決する別のソリューションについては、任意のXPath式を評価するために使用できるXSLTがあります(XSLTプロセッサでのdyn:evaluateサポートが必要です)。
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn">
<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
<xsl:template match="/">
<xsl:for-each select="dyn:evaluate($pattern)">
<xsl:value-of select="dyn:evaluate($value)"/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml
で実行します。
これらのツールを試してください:
xmlstarlet
:編集、選択、変換できます...デフォルトではインストールされません、xpath1xmllint
:多くの場合、デフォルトでlibxml2
、xpath1とともにインストールされます(改行を区切るには wrapper をチェックしてください)xpath
:PerlのモジュールXML::XPath
、xpath1を介してインストールされますxml_grep
:PerlのモジュールXML::Twig
、xpath1(xpathの使用制限)を介してインストールされますxidel
:xpath3saxon-lint
:私自身のプロジェクト、@ Michael KayのSaxon-HE Javaライブラリ、xpath3のラッパーxmllint
にはlibxml2-utils
が付属しています(--Shell
スイッチを使用して対話型シェルとして使用できます)
xmlstarlet
はxmlstarlet
です。
xpath
にはPerlのモジュールが付属しています XML::Xpath
xml_grep
にはPerlのモジュールが付属しています XML::Twig
xidel
はxidel
です
saxon-lint
使用 SaxonHE 9.6 、 XPath 3.x (+レトロ互換性)
例:
xmllint --xpath '//element/@attribute' file.xml
xmlstarlet sel -t -v "//element/@attribute" file.xml
xpath -q -e '//element/@attribute' file.xml
xidel -se '//element/@attribute' file.xml
saxon-lint --xpath '//element/@attribute' file.xml
。
Xidel を試すこともできます。リポジトリ内のパッケージにはありませんが、Webページからダウンロードするだけです(依存関係はありません)。
このタスクの単純な構文があります。
xidel filename.xml -e '//element/@attribute'
そして、XPath 2をサポートするこれらのツールの中でも珍しいものの1つです。
システムに既にインストールされている可能性が非常に高いパッケージの1つはpython-lxml
です。その場合、追加のパッケージをインストールせずにこれを実行できます。
python -c "from lxml.etree import parse; from sys import stdin; print '\n'.join(parse(stdin).xpath('//element/@attribute'))"
Maven pom.xmlファイルを照会する検索で、この質問に出くわしました。ただし、次の制限がありました。
私は成功せずに上記の多くを試しました:
私が遭遇した解決策は、安定しており、短く、多くのプラットフォームで動作し、成熟しているソリューションは、Rubyに組み込まれているrexml libです。
Ruby -r rexml/document -e 'include REXML;
p XPath.first(Document.new($stdin), "/project/version/text()")' < pom.xml
これを見つけるきっかけになったのは、次の記事です。
Saxonは、これをXPath 2.0だけでなく、XQuery 1.0および(商用バージョン)3.0でも行います。 Linuxパッケージとしてではなく、jarファイルとして提供されます。構文(簡単なスクリプトで簡単にラップできます)は
Java net.sf.saxon.Query -s:source.xml -qs://element/attribute
xsh にも興味があるかもしれません。それはあなたが文書であなたが好きなことをすることができるインタラクティブなモードを特徴とします:
open 1.xml ;
ls //element/@id ;
for //p[@class="first"] echo text() ;
clackeの答え は素晴らしいですが、ソースが通常のHTMLではなく整形式のXMLである場合にのみ機能すると思います。
したがって、通常のWebコンテンツ(必ずしも整形式のXMLではないHTMLドキュメント)に対して同じことを行うには:
echo "<p>foo<div>bar</div><p>baz" | python -c "from sys import stdin; \
from lxml import html; \
print '\n'.join(html.tostring(node) for node in html.parse(stdin).xpath('//p'))"
また、代わりにhtml5libを使用するには(Webブラウザーと同じ解析動作を確保するために-ブラウザーパーサーのように、html5libはHTML仕様の解析要件に準拠しています)。
echo "<p>foo<div>bar</div><p>baz" | python -c "from sys import stdin; \
import html5lib; from lxml import html; \
doc = html5lib.parse(stdin, treebuilder='lxml', namespaceHTMLElements=False); \
print '\n'.join(html.tostring(node) for node in doc.xpath('//p'))
Mikeとclackeの答えと同様に、pom.xmlファイルには通常dtdが含まれていないという事実を回避するpom.xmlファイルからビルドバージョンを取得するためのPythonワンライナー(python> = 2.5を使用)があります。デフォルトの名前空間なので、libxmlには整形式に見えません:
python -c "import xml.etree.ElementTree as ET; \
print(ET.parse(open('pom.xml')).getroot().find('\
{http://maven.Apache.org/POM/4.0.0}version').text)"
MacおよびLinuxでテストされており、追加のパッケージをインストールする必要はありません。
XML :: XSH および XML :: XSH2 に加えてgrep
のようなユーティリティは、 App::xml_grep2
および XML::Twig
(xml_grep
を含む) xml_grep2
ではなく)。これらは、迅速なonelinersまたはMakefile
ターゲットの大規模または多数のXMLファイルで作業する場合に非常に役立ちます。 XML::Twig
は、$Shell
やPerl
xmllint
のオファーよりも少し処理をしたい場合に、xstlproc
のスクリプティングアプローチに特に適しています。
アプリケーション名の番号付けスキームは、「2」バージョンが、他のモジュール(またはPerl
自体)の新しいバージョンを必要とする可能性のある本質的に同じツールの新しい/後であることを示しています。
Nokogiri自体にはコマンドラインツールが付属しており、gem install nokogiri
とともにインストールする必要があることに言及する必要があります。
このブログ投稿が便利 を見つけるかもしれません。
私のPythonスクリプト xgrep.py はまさにこれを行います。すべての属性attribute
の要素element
をファイルfilename.xml ...
で検索するには、次のように実行します。
xgrep.py "//element/@attribute" filename.xml ...
一致をカウントする-c
、一致する部分をインデントする-i
、ファイル名のみを出力する-l
など、出力を制御するためのさまざまなスイッチがあります。
このスクリプトはDebianまたはUbuntuパッケージとしては使用できませんが、その依存関係はすべて使用可能です。
私はいくつかのコマンドラインXPathユーティリティを試しましたが、グーグルとそれらの動作を理解するのに時間がかかりすぎることに気付いたので、私は必要なことをした最も簡単なXPathパーサーをPythonで書きました。
以下のスクリプトは、XPath式が文字列に評価される場合は文字列値を示し、結果がノードである場合はXMLサブノード全体を示します。
#!/usr/bin/env python
import sys
from lxml import etree
tree = etree.parse(sys.argv[1])
xpath = sys.argv[2]
for e in tree.xpath(xpath):
if isinstance(e, str):
print(e)
else:
print((e.text and e.text.strip()) or etree.tostring(e))
lxml
を使用します。これは、標準のPythonライブラリには含まれていない、Cで記述された高速XMLパーサーです。 pip install lxml
でインストールします。 Linux/OSXでは、Sudo
のプレフィックスが必要になる場合があります。
使用法:
python xmlcat.py file.xml "//mynode"
lxmlは、入力としてURLを受け入れることもできます。
python xmlcat.py http://example.com/file.xml "//mynode"
Enclosureノードの下のurl属性、つまり<Enclosure url="http:...""..>)
を抽出します。
python xmlcat.py xmlcat.py file.xml "//Enclosure/@url"
関係のない副次的注意として:偶然にWebページのマークアップに対してXPath式を実行したい場合は、Chrome devtoolsから直接実行できます。Chromeでページを右クリックし、[Inspect]を選択してから、DevToolsでコンソールは、XPath式を$x("//spam/eggs")
として貼り付けます。
このページのすべての著者を取得:
$x("//*[@class='user-details']/a/text()")
このプロジェクトは明らかにかなり新しいので、 https://github.com/jeffbr13/xq をチェックしてください。これはlxml
のラッパーのようですが、本当に必要なのはそれだけです(アドホックソリューションを投稿しました)他の回答でもlxmlを使用してください)
以下は、ネストされた要素elem1、elem2からこのタイプのXMLから1行のテキストにデータを抽出するxmlstarletの使用例です(名前空間の処理方法も示します)。
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<mydoctype xmlns="http://xml-namespace-uri" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml-namespace-uri http://xsd-uri" format="20171221A" date="2018-05-15">
<elem1 time="0.586" length="10.586">
<elem2 value="cue-in" type="outro" />
</elem1>
</mydoctype>
出力は
0.586 10.586 cue-in outro
このスニペットでは、-mはネストされたelem2と一致し、-vは属性値(式と相対アドレス指定)、-oリテラルテキスト、-nは改行を追加します。
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2' \
-v ../@time -o " " -v '../@time + ../@length' -o " " -v @value -o " " -v @type -n file.xml
Elem1からさらに属性が必要な場合は、次のようにできます(concat()関数も表示)。
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2/..' \
-v 'concat(@time, " ", @time + @length, " ", ns:elem2/@value, " ", ns:elem2/@type)' -n file.xml
名前空間(ns、-Nで宣言された)との(IMO不要)の複雑さに注意してください。xpathとxmlstarletをほとんどあきらめ、簡単なアドホックコンバーターを作成しました。