mpd*_*dio 9 php xml xpath namespaces simplexml
我有一个XML文档,它附加了一个默认命名空间,例如
<foo xmlns="http://www.example.com/ns/1.0">
...
</foo>
Run Code Online (Sandbox Code Playgroud)
实际上,这是一个符合复杂模式的复杂XML文档.我的工作是从中解析出一些数据.为了帮助我,我有一个XPath的电子表格.XPath是相当深层嵌套的,例如
level1/level2/level3[@foo="bar"]/level4[@foo="bar"]/level5/level6[2]
Run Code Online (Sandbox Code Playgroud)
生成XPath的人是模式的专家,所以我假设我不能简化它,或者使用对象遍历快捷方式.
我正在使用SimpleXML来解析所有内容.我的问题与如何处理默认命名空间有关.
由于根元素上有一个默认命名空间,我不能这样做
$xml = simplexml_load_file($somepath);
$node = $xml->xpath('level1/level2/level3[@foo="bar"]/level4[@foo="bar"]/level5/level6[2]');
Run Code Online (Sandbox Code Playgroud)
我必须注册命名空间,将其分配给前缀,然后在我的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]');
Run Code Online (Sandbox Code Playgroud)
从长远来看,添加前缀不会是可管理的.
是否有一种正确的方法来处理默认名称空间而无需使用XPath前缀?
使用空前缀不起作用($xml->registerXPathNamespace('', 'http://www.example.com/ns/1.0');).我可以指出默认的命名空间,例如
$xml = file_get_contents($somepath);
$xml = str_replace('xmlns="http://www.example.com/ns/1.0"', '', $xml);
$xml = simplexml_load_string($xml);
Run Code Online (Sandbox Code Playgroud)
但这是在绕过这个问题.
IMS*_*SoP 12
从在线阅读,这不仅限于任何特定的PHP或其他库,而是限于XPath本身 - 至少在XPath版本1.0中
XPath 1.0不包含任何"默认"命名空间的概念,因此无论元素名称如何出现在XML源中,如果它们具有绑定到它们的命名空间,则它们的选择器必须以表单的基本XPath选择器为前缀ns:name.请注意,这ns是在XPath处理器中定义的前缀,而不是正在处理的文档,因此xmlns与XML表示中的属性使用方式无关.
参见例如这个"常见的XSLT错误"页面,讨论密切相关的XSLT 1.0:
要在XPath中访问命名空间元素,必须为其命名空间定义前缀.[...]不幸的是,XSLT 1.0版没有类似于默认命名空间的概念; 因此,您必须一次又一次地重复名称空间前缀.
根据对类似问题的回答,XPath 2.0 确实包含"默认命名空间"的概念,上面链接的XSLT页面也在XSLT 2.0的上下文中提到了这一点.
不幸的是,PHP中的所有内置XML扩展都是建立在libxml2和libxslt库的基础之上的,它们只支持XPath和XSLT的1.0版本.
因此,除了预处理文档而不使用命名空间之外,您唯一的选择是找到可以插入PHP的XPath 2.0处理器.
(顺便说一句,值得注意的是,如果你的XML文档中有无前缀的属性,它们在技术上不属于默认命名空间,而是根本没有命名空间;请参阅XML命名空间和未加前缀的属性以讨论命名空间的这种奇怪之处规范.)
| 归档时间: |
|
| 查看次数: |
3642 次 |
| 最近记录: |