Поведение XPath с конфликтующими префиксами пространства имен XML - PullRequest
3 голосов
/ 24 февраля 2020

Рассмотрим следующее XML:

<?xml version="1.0" encoding="utf-8"?>
<movies xmlns:en="http://english-language.com/">
    <en:movie>
        <title>The Godfather</title>
    </en:movie>
    <en:movie>
        <title>Saving Private Ryan</title>
    </en:movie>
    <something-something xmlns:en="http://english.com/">
        <en:movie>
            <title>The Fellowship of the Ring</title>
        </en:movie>
    </something-something>
</movies>

Этот код ниже будет соответствовать Крестный отец и Сохранение рядового Райана . Но почему? Я ожидал, что это не удастся. Похоже, что запрос игнорирует имя пространства имен (URI) в пользу префикса пространства имен

$xpath      = new DOMXpath($dom);
$xpath->registerNamespace('en', 'http://complete-nonsense');
$elements   = $xpath->query("//en:movie");

Я ожидал, что приведенный ниже код будет соответствовать Братство Кольца , но опять-таки оно соответствует Крестный отец и Спасение рядового Райана .

$xpath      = new DOMXpath($dom);
$xpath->registerNamespace('en', 'http://english.com/');
$elements   = $xpath->query("//en:movie");

Только теперь URI, кажется, имеет какое-то значение, теперь он соответствует Братству Кольцо .

$xpath      = new DOMXpath($dom);
$xpath->registerNamespace('english', 'http://english.com/');
$elements   = $xpath->query("//english:movie");

Почему это так? Что-то не так с реализацией PHP или как?

1 Ответ

2 голосов
/ 24 февраля 2020

DOMXpath::evaluate() / DOMXpath::query() зарегистрировать определения пространства имен текущего узла контекста поверх зарегистрированных вручную. В основном документ переопределит пространство имен для префикса. Третий аргумент (начиная с PHP> = 5.3.3) может отключить автоматическую регистрацию c:

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('en', 'http://english.com/');

// the xmlns:en from the document element overrides the registration
var_dump($xpath->evaluate('normalize-space(//en:movie)'));
// automatic registration disabled - works correctly
var_dump($xpath->evaluate('normalize-space(//en:movie)', NULL, FALSE));

Вывод:

string(13) "The Godfather"
string(26) "The Fellowship of the Ring"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...