61

我正在尝试查询 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
        content=foo@bar.com
    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="foo@bar.com" service="MSN">
<event type="windowOpened" sender="foo@bar.com" time="2011-11-22T00:34:43-03:00"></event>
<message sender="foo@bar.com" 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>
4

3 回答 3

101

我不使用 xmllint,但我认为您的 XPath 不起作用的原因是因为您的 doc.xml 文件使用了默认命名空间 ( http://purl.org/net/ulf/ns/0.4-02)。

据我所知,您有两个选择。

A、在shell模式下使用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'with,local-name()因此您可以确保返回您打算返回的内容。

于 2011-11-25T07:48:21.853 回答
11

我意识到这个问题现在已经很老了,但如果它可以帮助某人......

有同样的问题,这是由于 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 "..." -
于 2019-04-10T02:50:03.983 回答
0

如果你被允许在你的环境中安装 powershell(它也适用于 Linux),你可以这样做:

Select-Xml -XPath '/ns:chat' -Namespace $Namespace .\doc.xml | foreach { $_.Node }
   xmlns   : http://purl.org/net/ulf/ns/0.4-02
   account : foo@bar.com
   service : MSN
   event   : event
   message : message

当然,这里适用于 xpath 的所有相同规则。要访问节点的文本内容:

Select-Xml -XPath '/ns:chat/ns:message' -Namespace $Namespace .\doc.xml |foreach {$_.Node.InnerXML }
<div xmlns="http://purl.org/net/ulf/ns/0.4-02"><span style="color: #000000; font-family: Helvetica; font-size: 12pt;">hi</span></div>

或者 sender 属性的内容:

Select-Xml -XPath '/ns:chat/ns:message/@sender' -Namespace $Namespace .\doc.xml |foreach {$_.Node }

#text
-----
foo@bar.com
于 2021-04-29T16:31:49.277 回答