llanato
llanato

Reputation: 2503

XML/DOM - Can't update empty node value

I'm having difficulty modifying values in an XML file, I have the below code snippet. The XML snippet below is a very cut down version of the XML file, I keep getting this error when I run the code:

Error

Warning: Creating default object from empty value in updateXML.php

PHP

$doc = new DOMDocument();
$doc->load($vNewFile);
$vPayment = $doc->getElementsByTagName("Payment");
foreach ($vPayment AS $vPaymt) {
    $vPaymt->Name->nodeValue = self::NAME;
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<Document>
    <Customer>
        ...
        <Payment>
            <Name></Name>
            ...
        </Payment>
        ...
    </Customer>
</Document>

Any help with this issue is greatly appreciated as I'm stupid, just can't figure it out.

Upvotes: 0

Views: 303

Answers (1)

ThW
ThW

Reputation: 19512

The problem is:

$vPaymt->Name->nodeValue = self::NAME;

It is not related to DOM. Here is another source that reproduces the error message:

$o = new stdClass();
$o->PropertyName->SubPropertyName = 23;

Message:

Warning: Creating default object from empty value in /tmp/ex... on line 4

What happens is that $vPaymt is an object (a DOMElement), but $vPaymt->Name is a non existing property. You use that non existing property as an object by writing a property of it. PHP initializes it as a default object and warns you about that.

DOM has no autmatic mapping for child elements (like SimpleXML). You should use XPath to fetch the Name node.

$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<Document>
    <Customer>
        <Payment>
            <Name></Name>
        </Payment>
    </Customer>
</Document>
XML;

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);

foreach ($xpath->evaluate('//Payment/Name') as $node) {
  $node->nodeValue = '';
  $node->appendChild($dom->createTextNode('FOO'));
}

echo $dom->saveXml();

Output:

<?xml version="1.0" encoding="UTF-8"?>
<Document>
    <Customer>
        <Payment>
            <Name>FOO</Name>
        </Payment>
    </Customer>
</Document>

WARNING!

Never write DOMNode::$nodeValue with a string from a variable. It does not fully escape the provided string. Setting an empty string is fine (no characters to escape). Always create a text node and append it to avoid broken XML.

Upvotes: 1

Related Questions