2017-02-14 85 views
0

私は多くのメディアフィールドを持つXMLファイルを持っています。 XML例は、xmllintを使用して同じ名前のフィールドを複数抽出する

<root> 
    <item> 
     <name>Item 1</name> 
     <mediaList> 
      <media> 
       <name>Name 1</name> 
       <URL><![CDATA[http://example.com/image1.jpg]]></URL> 
      </media> 
      <media> 
       <name>Name 2</name> 
       <URL><![CDATA[http://example.com/image2.jpg]]></URL> 
      </media> 
     </mediaList> 
    </item> 
    <item> 
     <name>Item 2</name> 
     <mediaList> 
      <media> 
       <name>Name 3</name> 
       <URL><![CDATA[http://example.com/image3.jpg]]></URL> 
      </media> 
      <media> 
       <name>Name 4</name> 
       <URL><![CDATA[http://example.com/image4.jpg]]></URL> 
      </media> 
     </mediaList> 
    </item> 
</root> 

すべての項目が同じ方法で構築されています。 XPathでXMLLintを使用すると、すべてのURLのリストを取得しようとしています。しかし、これまでのところ、私はまだそれについて最善の方法を見つけることができませんでした。私はそれを試してみた方法のいくつかは以下のとおりです

xmllint --xpath "string(/root/item/mediaList/URL)" file.xml >> log.txt

この1つは素敵なURLを返しますが、(私の唯一の1画像を与える)最初の項目の後に停止し

xmllint --xpath "/root/item/mediaList/URL" file.xml >> log.txt

この私にすべてのアイテムを与えますが、すべてが同じ行にあり、各アイテムに<URL><![CDATA[http://example.com/image.jpg]]></URL>と表示されます。

xmllint --xpath "/root/item/mediaList/URL/text()" file.xml >> log.txt

これは最も近いが、それでもすべて1行で再びその周り<![CDATA[]]>タグを返し、。

私もアイテムをループしてみましたが、これは非常に遅く、正常に動作しませんでした。

私が目指していた結果がお互いの下にあるすべての画像とテキストファイルなので、のように:

http://example.com/image1.jpg 
http://example.com/image2.jpg 
http://example.com/image3.jpg 
http://example.com/image4.jpg 
+1

'--nocdata'オプションは、各CDATAノードからテキストを抽出します。私はどのように別の行に各URLを取得するか分からない。 – chepner

+0

ありがとう!良いもの。考えるべき問題が1つ少なくなる。 –

答えて

2

xmllintは、複数のXPathの一致に対してstring(...)をサポートしていません。 (したがって、最初の結果のみが表示されます)。

あなたが好きxmlstarletを使用することができます。

xmlstarlet sel -T -t -m /root/item/mediaList/media/URL -v . -n file.xml 

、それのように(インストールXML::LibXMLモジュールで)

http://example.com/image1.jpg 
http://example.com/image2.jpg 
http://example.com/image3.jpg 
http://example.com/image4.jpg 

かもPerlを生成します。

perl -MXML::LibXML -E 'say $_->to_literal for XML::LibXML->load_xml(location=>q{file.xml})->findnodes(q{/root/item/mediaList/media/URL})' 

も同じ結果を生成します上記のように。

+0

'xmlstarlet'オプションは私のためにそれを解決しました。ありがとうございました。 –

0

私はあなたがW3C文書で、パーサを変更すべきだと思う:

各CDATAセクション内の文字は文字データとして扱われます。 したがって、ソースドキュメントの<![CDATA [<]]>は、 <と同じ扱いになります。どちらも、 ツリー内のテキストノード内に単一の<文字をもたらします。したがって、CDATAセクションは、<![CDATA [および]]> が取り除かれ、<および&がすべて、それぞれ、<および &に置き換えられたように扱われます。 CDATAは自動的に削除されます

、私はPythonでそれをテスト:

tree = etree.fromstring(xml) 
tree.xpath('//URL/text()') 

アウト:あなたのXPathが正しい

['http://example.com/image1.jpg', 
'http://example.com/image2.jpg', 
'http://example.com/image3.jpg', 
'http://example.com/image4.jpg'] 

関連する問題