更改DOM后的PHP XPath查询错误

时间:2013-06-28 06:28:19

标签: php dom xpath

在尝试XPath查询新创建的节点时,我总是收到消息PHP Notice: Trying to get property of non-object in ...

我的XML文件如下所示:

<products xmlns='http://example.com/products'>
    <product id='1'>
        <name>Product name</name>
    </product>
</products>

我的PHP文件本质上应用XPath查询来获取现有的<product>,并对其<name>应用第二个查询。这很好。

然后我将一个带有子<product>的新<name>插入到DOM根元素中,并尝试对新创建的元素进行第二次查询。获取该属性可以正常工作,但第二个查询(应该获得第一个子<name>的值)会因PHP通知Trying to get property of non-object in ...而失败。

$xmlFile = __DIR__ . '/products.xml';

$xml = new DOMDocument();
$xml->load($xmlFile);
$xml->formatOutput = true;

$xpath = new DOMXPath($xml);
$xpath->registerNamespace('p', $xml->lookupNamespaceUri($xml->namespaceURI));

/*
 * query the first product's ID and name
 */

$product1 = Product::$xpath->query("//p:product[@id=1]")->item(0);

$product1Id = $product1->attributes->getNamedItem('id')->nodeValue;
// => "1"
$product1Name = $xpath->query("p:name", $product1)->item(0)->nodeValue;
// => "Product name"

/*
 * create the second product
 */

$product2Node = $xml->createElement('product');
$product2Node->setAttribute('id', '2');

$product2NameNode = $xml->createElement('name', 'Test');
$product2Node->appendChild($product2NameNode);

$product2 = $xml->documentElement->appendChild($product2Node);

/*
 * query the second product's ID and name
 */

$product2Id = $product2->attributes->getNamedItem('id')->nodeValue;
// => "2"
$product2Name = $xpath->query("p:name", $product2)->item(0)->nodeValue;
// => PHP Notice:  Trying to get property of non-object in ...

$xml->save($xmlFile);

运行PHP文件后,XML看起来是正确的:

<products xmlns='http://example.com/products'>
    <product id='1'>
        <name>Product name</name>
    </product>
    <product id='2'>
        <name>Test</name>
    </product>
</products>

我真的坚持这个,我试图在查询之前保存XML,保存后重新加载XML,重新创建XPath对象等。

1 个答案:

答案 0 :(得分:1)

我认为您需要使用createElementNS函数(http://php.net/manual/en/domdocument.createelementns.php;您可能还需要检查setAttributeNS - http://www.php.net/manual/en/domelement.setattributens.php)而不是createElement才能明确表明这些元素属于http://example.com/products命名空间。

$product2Node = $xml->createElementNS('http://example.com/products', 'product');
$product2Node->setAttribute('id', '2');

$product2NameNode = $xml->createElementNS('http://example.com/products', 'name', 'Test');
$product2Node->appendChild($product2NameNode);

(有点令人惊讶的是,在保存之后重新加载XML并没有解决这个问题,但是如果没有看到尝试重新加载的代码,则很难知道可能出现的问题。)