web-dev-qa-db-ja.com

xmllintがxpathで適切にクエリに失敗する

Adiumによって生成されたxmlファイルを照会しようとしています。 xmlwfは、整形式であることを示しています。 xmllintのデバッグオプションを使用すると、次の結果が得られます。

$ xmllint --debug doc.xml
DOCUMENT
version=1.0
encoding=UTF-8
URL=doc.xml
standalone=true
  ELEMENT chat
    default namespace href=http://purl.org/net/ulf/ns/0.4-02
    ATTRIBUTE account
      TEXT
        [email protected]
    ATTRIBUTE service
      TEXT compact
        content=MSN
    TEXT compact
      content= 
    ELEMENT event
      ATTRIBUTE type

すべてがうまく解析されるようです。ただし、最も単純なものでもクエリを実行しようとしても、何も得られません。

$ xmllint --xpath '/chat' doc.xml 
XPath set is empty

何が起こっていますか? xpathを使用してまったく同じクエリを実行すると、正しい結果が返されます(ただし、結果の間に改行はありません)。何か間違ったことをしているのですか、それともxmllintが適切に機能していないのですか?

同じ動作を示すxmlの匿名化された短いバージョンは次のとおりです。

<?xml version="1.0" encoding="UTF-8" ?>
<chat xmlns="http://purl.org/net/ulf/ns/0.4-02" account="[email protected]" service="MSN">
<event type="windowOpened" sender="[email protected]" time="2011-11-22T00:34:43-03:00"></event>
<message sender="[email protected]" time="2011-11-22T00:34:43-03:00" alias="foo"><div><span style="color: #000000; font-family: Helvetica; font-size: 12pt;">hi</span></div></message>
</chat>
46
ailnlv

Xmllintは使用しませんが、XPathが機能しない理由は、doc.xmlファイルがデフォルトのネームスペース(_http://purl.org/net/ulf/ns/0.4-02_)を使用しているためだと思います。

私が見ることができるものから、あなたには2つのオプションがあります。

A。シェルモードでxmllintを使用し、プレフィックスで名前空間を宣言します。その後、XPathでそのプレフィックスを使用できます。

_    xmllint --Shell doc.xml
    / > setns x=http://purl.org/net/ulf/ns/0.4-02
    / > xpath /x:chat_

B。local-name()を使用して要素名を一致させます。

    xmllint --xpath /*[local-name()='chat']

namespace-uri()='http://purl.org/net/ulf/ns/0.4-02'local-name()とともに使用することもできます。これにより、確実に返そうとしているものを正確に返すことができます。

77
Daniel Haley

私はこの質問が今では非常に古いことを知っていますが、それが誰かを助ける場合に...

同じ問題を抱えていたのは、名前空間を持つXMLによるものでした(また、XMLのさまざまな場所で複製されることもありました)。 xmllintを使用する前に名前空間を削除するのが最も簡単であることがわかりました。

sed -e 's/xmlns=".*"//g' file.xml | xmllint --xpath "..." -

私の場合、XMLはUTF-16であったため、最初にUTF-8に変換する必要がありました(sedの場合):

iconv -f utf16 -t utf8 file.xml | sed -e 's/encoding="UTF-16"?>/encoding="UTF-8"?>/' | sed -e 's/xmlns=".*"//g' | xmllint --xpath "..." -
2
codesniffer