2008-12-09 84 views
12

供应商稍微更改了XML标题后发生了一件奇怪的事情。我曾经可以使用XPath阅读的东西,但现在我甚至不能用PHP simplexml:为什么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" [ 
<!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" 
> 
... 

回答

25

这很可能是因为他们已经在其文档中引入了默认名称空间(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:"前缀上元素。这里是一些额外的信息:http://people.ischool.berkeley.edu/~felix/xml/php-and-xmlns.html

编辑:按照the spec

The registerXPathNamespace() function创建下一个XPath查询前缀/ ns的上下文。

这意味着将有充分的XPath查询之前调用,因此功能包XPath查询将做到自然的事情:

function simplexml_xpath_ns($element, $xpath, $xmlns) 
{ 
    foreach ($xmlns as $prefix_uri) 
    { 
     list($prefix, $uri) = explode("=", $prefix_uri, 2); 
     $element->registerXPathNamespace($prefix, $uri); 
    } 
    return $element->xpath($xpath); 
} 

用法:

$xmlns = ["n=http://iptc.org/std/NewsML/2003-10-10/"]; 
$result = simplexml_xpath_ns($xml, '/n:NewsML', $xmlns); 
+1

谢谢一堆!此外,似乎你必须在每个xpath请求之前注册命名空间。如果你可以添加这个到你的答案,这将是完美的;) – 2008-12-09 09:18:07