发送报头时SimpleXML addChild问题

2022-08-12 00:00:00 php simplexml

我有以下代码:

$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();
我可以通过$xml创建带有属性的子节点,但不能通过$node(子节点的子节点)创建,为什么?我收到错误error on line 2 at column 66: expected '>' 从文档中可以看出,addChild函数返回子对象的SimpleXmlElement。 通过取消注释行$node->addChild('nodeChild attr="node Child"');进行检查 此外,只有在发送Header时才会发生这种情况,如果我评论Header并执行以下操作,我可以在页面源代码中看到正确的XML:

 $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();

我的PHP版本是5.4.9


解决方案

您看到的错误不是来自SimpleXML,而是来自您的浏览器--这就是更改HTTP头有效的原因。有了这一行,浏览器知道页面是XML,并检查它是否有效;如果没有它,它就假设它是HTML,并且更宽松:

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

如果您在浏览器中使用"查看源代码",您会发现在这两种情况下来自PHP的实际输出是相同的。另一个不错的测试是将内容类型设置为text/plain,这意味着浏览器根本不会解释输出,只按原样显示它。

因此,出于某种原因,SimpleXML正在生成无效的XML。这是因为the ->addChild() method仅将要添加的元素的名称作为其第一个参数,在您的情况下'erroNode';您传入的无效名称也包含属性,应在以后使用->addAttribute()添加。


如果我们进一步简化该示例,并查看生成的XML,我们可以看到发生了什么(这里是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 "
";

// 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();

这将输出以下内容:

<?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>

第一个版本的XML似乎正在做正确的事情,因为它创建了一个"自结束标记"。但是,在第二个示例中,您可以看到SimpleXML认为标记名是'testNode attr="test Attribute"',而不仅仅是'testNode',因为我们就是这么告诉它的。

结果是它尝试使用该"name"放置一个结束标记,并以</testNode attr="test Attribute">结束,而</testNode attr="test Attribute">不是有效的XML。

可以说,SimpleXML应该可以保护您免受这种情况的影响,但现在您知道了,您可以轻松地修复代码(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();

现在,SimpleXML知道标记仅称为'testNode',因此可以在需要时创建正确的结束标记:

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

相关文章