0

我正在处理的一个项目需要解析来自供应商的 XML 文档,但他们提供了无效的 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
}
4

1 回答 1

0

请注意,某些 XML 视图(例如 Firefox)不显示 xmlns 属性(命名空间定义)。如果您没有收到错误消息(也就是 XML 有效),请打开源代码以检查命名空间定义。

在您发布的来源中,缺少“金额”属性的前缀,因此它不会显示任何内容。

$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);
于 2014-10-21T08:56:43.813 回答