我有一个 XML 文档,它附加了一个默认的命名空间,例如
<foo xmlns="http://www.example.com/ns/1.0">
...
</foo>
实际上,这是一个符合复杂模式的复杂 XML 文档。我的工作是从中解析出一些数据。为了帮助我,我有一个 XPath 电子表格。 XPath 嵌套很深,例如
level1/level2/level3[@foo="bar"]/level4[@foo="bar"]/level5/level6[2]
生成 XPath 的人是模式方面的专家,所以我假设我无法简化它,或者使用对象遍历快捷方式。
我正在使用 SimpleXML解析一切。我的问题与默认 namespace 的处理方式有关。
因为在根元素上有一个默认的命名空间,我不能这样做
$xml = simplexml_load_file($somepath);
$node = $xml->xpath('level1/level2/level3[@foo="bar"]/level4[@foo="bar"]/level5/level6[2]');
我必须register the namespace ,将其分配给一个前缀,然后在我的 XPath 中使用该前缀,例如
$xml = simplexml_load_file($somepath);
$xml->registerXPathNamespace('myns', 'http://www.example.com/ns/1.0');
$node = $xml->xpath('myns:level1/myns:level2/myns:level3[@foo="bar"]/myns:level4[@foo="bar"]/myns:level5/myns:level6[2]');
从长远来看,添加前缀是不可管理的。
是否有一种无需使用 XPath 前缀即可处理默认 namespace 的正确方法?
使用空前缀不起作用 ($xml->registerXPathNamespace('', 'http://www.example.com/ns/1.0');
)。我可以串出默认的命名空间,eg
$xml = file_get_contents($somepath);
$xml = str_replace('xmlns="http://www.example.com/ns/1.0"', '', $xml);
$xml = simplexml_load_string($xml);
但这是在回避问题。
最佳答案
从一些在线阅读来看,这并不局限于任何特定的 PHP 或其他库,而是 XPath 本身——至少在 XPath 1.0 版中是这样
XPath 1.0 不包含任何“默认”命名空间的概念,因此无论元素名称如何出现在 XML 源中,如果它们绑定(bind)了命名空间,则它们的选择器必须在基本 XPath 选择器中添加前缀形式为 ns:name
。请注意,ns
是在 XPath 处理器中定义的前缀,而不是由正在处理的文档定义的,因此与 xmlns
属性在 XML 表示中的使用方式无关。
参见例如this "common XSLT mistakes" page ,谈论密切相关的 XSLT 1.0:
To access namespaced elements in XPath, you must define a prefix for their namespace. [...] Unfortunately, XSLT version 1.0 has no concept similar to a default namespace; therefore, you must repeat namespace prefixes again and again.
根据 an answer to a similar question , XPath 2.0 确实包含“默认 namespace ”的概念,并且上面链接的 XSLT 页面也在 XSLT 2.0 的上下文中提到了这一点。
不幸的是,PHP 中的所有内置 XML 扩展都是构建在 libxml2 之上的和 libxslt库,仅支持 1.0 版的 XPath 和 XSLT。
因此,除了预处理文档以不使用命名空间之外,您唯一的选择是找到一个可以插入 PHP 的 XPath 2.0 处理器。
(顺便说一句,值得注意的是,如果您的 XML 文档中有未加前缀的属性,它们在技术上不在默认 namespace 中,而是根本不在任何 namespace 中;参见 XML Namespaces and Unprefixed Attributes用于讨论命名空间规范的这种奇怪之处。)
关于php - SimpleXML 中用于默认 namespace 的 XPath,无需前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21143846/