PHP simplexml:为什么xpath停止工作?
供应商稍微更改了XML头之后发生了一件奇怪的事情。我以前能够使用xpath阅读内容,但现在我甚至无法用xpath获得回复PHP simplexml:为什么xpath停止工作?,php,xml,xpath,simplexml,Php,Xml,Xpath,Simplexml,供应商稍微更改了XML头之后发生了一件奇怪的事情。我以前能够使用xpath阅读内容,但现在我甚至无法用xpath获得回复 $xml->xpath('/'); 他们改变了这个 <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE NewsML SYSTEM "http://www.newsml.org/dl.php?fn=NewsML/1.2/specification/NewsML_1.2.dtd" [ <!E
$xml->xpath('/');
他们改变了这个
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE NewsML SYSTEM "http://www.newsml.org/dl.php?fn=NewsML/1.2/specification/NewsML_1.2.dtd" [
<!ENTITY % nitf SYSTEM "http://www.nitf.org/IPTC/NITF/3.4/specification/dtd/nitf-3-4.dtd">
%nitf;
]>
<NewsML>
...
...
为此:
<?xml version="1.0" encoding="iso-8859-1"?>
<NewsML
xmlns="http://iptc.org/std/NewsML/2003-10-10/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://iptc.org/std/NewsML/2003-10-10/ http://www.iptc.org/std/NewsML/1.2/specification/NewsML_1.2.xsd http://iptc.org/std/NITF/2006-10-18/ http://contentdienst.pressetext.com/misc/nitf-3-4.xsd"
>
...
...
这很可能是因为他们引入了默认名称空间(xmlns=”http://iptc.org/std/NewsML/2003-10-10/“
)输入到他们的文档中。简单地说,SimpleXML对默认名称空间的支持不是很好
是否可以尝试显式注册命名空间前缀:
$xml->registerXPathNamespace("n", "http://iptc.org/std/NewsML/2003-10-10/");
$xml->xpath('/n:NewsML');
您必须调整XPath表达式,以便在每个元素上使用“n:
前缀。以下是一些附加信息:
编辑:根据:
为下一个XPath查询创建前缀/ns上下文
这意味着必须在每次XPath查询之前调用它,因此包装XPath查询的函数是很自然的事情:
函数simplexml\u xpath\n($element,$xpath,$xmlns)
{
foreach($xmlns作为$prefix_uri)
{
列表($prefix,$uri)=分解(“=”,$prefix_uri,2);
$element->registerXPathNamespace($prefix,$uri);
}
返回$element->xpath($xpath);
}
用法:
$xmlns=[“n=http://iptc.org/std/NewsML/2003-10-10/"];
$result=simplexml\u xpath\n($xml,/n:newxml',$xmlns);
非常感谢!此外,似乎在每个xpath请求之前都必须注册名称空间。。如果你能在答案中加上这个,那就太完美了;)谢谢这修复了我对Google Earth(KML)文件的XPATH查询。只有从XML文件中删除xmlns属性,这才有效。为什么需要注册名称空间?为什么名称空间不被视为根元素上的属性?@Jakobud因为名称空间不仅仅是属性,它们改变了整个元素。把它们想象成……颜色。思维实验:
为默认值(黑色)<代码>设置新的默认值。现在整个元素(及其子元素!)都是红色的。现在,xpath('//foo')
将只选择黑色(这就是它的工作方式)。必须使用注册表XPathNamespace(“红色”、“rgb(255,0,0)”)使其识别红色。。现在您可以执行xpath('//red:foo')
。(注意:
将元素保留为默认值,但引入前缀red
,以供以后使用,即
)