SimpleXML addChild issue when header sent

烈酒焚心 提交于 2020-01-06 15:14:18

问题


I have this code :

$xml = new SimpleXMLElement('<myxml></myxml>');
$xml->addChild('testNode attr="test Attribute"');
$node = $xml->addChild('erroNode attr="My Child node causes error -> expect >"');
//$node->addChild('nodeChild attr="node Child"');
header('Content-type: text/xml');
echo $xml->asXML();
exit();

I can create a childnode with attributes via $xml, but not with $node(child's child), Why? i get the error error on line 2 at column 66: expected '>' From the docs it say that the addChild function returns a SimpleXmlElement of the child. Check by uncommenting the commented line $node->addChild('nodeChild attr="node Child"'); Also it only happens when header is sent, if i comment header and do like below i can see the correct xml in page source :

 $xml = new SimpleXMLElement('<myxml></myxml>');
    $xml->addChild('testNode attr="test Attribute"');
    $node = $xml->addChild('erroNode attr="My Child node causes error -> expect >"');
    $node->addChild('nodeChild attr="node Child"');
    //header('Content-type: text/xml');
    echo $xml->asXML();
    exit();

My PHP version is 5.4.9


回答1:


The error you are seeing is not coming from SimpleXML, but from your browser - that's why changing the HTTP header works. With this line, the browser knows the page is XML, and checks that it's valid; without it, it assumes it's HTML, and is more lenient:

header('Content-type: text/xml');

If you use "View Source" in your browser, you'll find that the actual output from PHP is the same in both cases. Another nice test is to set the content-type to text/plain instead, which means the browser won't interpret the output at all, just show it as-is.

So, for some reason, SimpleXML is generating invalid XML. This is because the ->addChild() method takes as its first argument just the name of the element to add, in your case 'erroNode'; you are passing in an invalid name that also includes attributes, which should be added later with ->addAttribute().


If we simplify the example a bit further, and look at the XML generated, we can see what's going on (here's an online demo):

// Make browser show plain output
header('Content-type: text/plain');

// Working example
$xml = new SimpleXMLElement('<myxml></myxml>');
$xml->addChild('testNode attr="test Attribute"');
echo $xml->asXML();

echo "\n";

// Broken example
$xml = new SimpleXMLElement('<myxml></myxml>');
$node = $xml->addChild('testNode attr="test Attribute"');
$node->addChild('test');
echo $xml->asXML();Child('testNode attr="test Attribute"');
$node->addChild('test');
echo $xml->asXML();

This outputs the below:

<?xml version="1.0"?>
<myxml><testNode attr="test Attribute"/></myxml>

<?xml version="1.0"?>
<myxml><testNode attr="test Attribute"><test/></testNode attr="test Attribute"></myxml>

The first version of the XML appears to be doing the right thing, because it has created a "self-closing tag". However, in the second, you can see that SimpleXML thinks that the tag name is 'testNode attr="test Attribute"', not just 'testNode', because that's what we told it.

The result is that it tries to put a closing tag with that "name", and ends up with </testNode attr="test Attribute">, which isn't valid XML.

Arguably, SimpleXML should protect you against this kind of thing, but now that you know, you can easily fix the code (demo):

// Make browser show plain output
header('Content-type: text/plain');

// Fixed example
$xml = new SimpleXMLElement('<myxml></myxml>');
$node = $xml->addChild('testNode');
$node->addAttribute('attr', 'test Attribute');
$node->addChild('test');
echo $xml->asXML();

Now, SimpleXML knows that the tag is just called 'testNode', so can create the correct closing tag when it needs to:

<?xml version="1.0"?>
<myxml><testNode attr="test Attribute"><test/></testNode></myxml>


来源:https://stackoverflow.com/questions/21379760/simplexml-addchild-issue-when-header-sent

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!