DOMNode::getAttribute с пространством имен, которое не определено

Проект, над которым я работаю, должен проанализировать XML-документ у поставщика, но он предоставил недопустимый XML, имеющий атрибуты с пространствами имен, которые не были объявлены. getAttribute($name) игнорирует, когда я пробую оба $node->getAttribute('prod:amount') а также $node->getAttribute('amount')

Я что-то делаю не так или есть способ каким-то образом подделать определение?

Редактирование Предоставление выдержки XML и PHP.

XML:

<order>
    <item id="85127" prod:id="1397" prod:amount="12.99">
        <desc><![CDATA[...]]></desc>
    </item>
    <item id="85128" prod:id="93" prod:amount="24.99">
        <desc><![CDATA[...]]></desc>
    </item>
    ...
</order>

PHP:

$doc = new DOMDocument;
$doc->load('URI');
foreach($doc->getElementsByTagName("item") as $node) {
    $cost = $node->getAttribute("amount");
    $id = $node->getAttribute("prod:id");
    print_r($cost); //never outputs
}

1 ответ

Имейте в виду, что некоторые представления XML (например, Firefox) не показывают атрибуты xmlns (определения пространства имен). Если вы не получите сообщение об ошибке (или XML-код действителен), откройте исходный код, чтобы проверить определения пространств имен.

В опубликованном вами источнике отсутствует префикс атрибута amount, поэтому он ничего не отображает.

$cost = $node->getAttribute("prod:amount");

Но не стоит полагаться на префиксы пространства имен, определенные в документе. Лучший способ - использовать само пространство имен.

$xml = <<<'XML'
<order xmlns:prod="urn:products">
    <item id="85127" prod:id="1397" prod:amount="12.99"></item>
    <item id="85128" prod:id="93" prod:amount="24.99"></item>
</order>
XML;

const XMLNS_PROD = 'urn:products';

$doc = new DOMDocument;
$doc->loadXml($xml);
foreach($doc->getElementsByTagName("item") as $node) {
    $cost = $node->getAttributeNS(XMLNS_PROD, "amount");
    $id = $node->getAttributeNS(XMLNS_PROD, "id");
    var_dump($id, $cost);
}

Выход:

string(4) "1397"
string(5) "12.99"
string(2) "93"
string(5) "24.99"

Так что если здесь действительно нет определения пространства имен, то вы можете "восстановить" XML, добавив его. Это обходной путь, реальное решение - исправить XML в его источнике.

$xml = str_replace('<order>', '<order xmlns:prod="urn:products">', $xml);
$doc = new DOMDocument;
$doc->loadXml($xml);
Другие вопросы по тегам