PHP simplexml: почему перестает работать xpath? - PullRequest
12 голосов
/ 09 декабря 2008

Странная вещь произошла после того, как поставщик немного изменил заголовок XML. Раньше я мог читать вещи с помощью 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"
>
...

1 Ответ

25 голосов
/ 09 декабря 2008

Скорее всего, это потому, что они ввели пространство имен по умолчанию (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.

РЕДАКТИРОВАТЬ: Согласно спецификации :

Функция registerXPathNamespace() создает контекст префикса / ns для следующего запроса 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);
...