2008-12-09 3 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.

EDIT: В соответствии с the spec:

The registerXPathNamespace() function создает префикс/нс контекст для следующего запроса XPath.

Это означает, что он должен быть вызван до каждого запроса 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

Смежные вопросы