PHP和XML创建:错误父节点


PHP & XML Creation: Node in wrong parent

我目前正在MVC风格的基于OOP的PHP项目上工作。对于我的项目,我需要创建/发送/接收/处理xml。

现在我有一个大问题与创建xml结构与DOMDocument。每次我创建一个没有属性的新xml节点时,如果这个节点,之后的所有节点都将是子节点!

换句话说:我不能创建一个空xml节点没有之后的所有节点是这个空节点的子节点!

这个问题困扰我一段时间了,但我真的需要我现在处理XML创建的方式。除了一些类似的问题,我找不到任何解决方案。

这个PHP测试我的XmlHandler-Class,它创建XML-Request:

Test.php:

<?php
include "Handler/XmlHandler.php";

$xmlHandler=new XmlHandler();
$xmlHandler->CreateNewXmlInstance();
$root = $xmlHandler->CreateRootNode('RootNode');
$l1 = $xmlHandler->AppendNodeWithChild($root, "NodeLevel1", "Text1 - This node one has text");
$l2 = $xmlHandler->AppendNodeWithChild($root, "NodeLevel2", "Text2 - Next node Level3 level is not gonna have text");
$l21 = $xmlHandler->AppendNodeWithChild($l2, "NodeLevel2_1", "Text2_1 - This node will be a child of Level2, everything fine");
$l3 = $xmlHandler->AppendNodeWithChild($root, "NodeLevel3", "");
$l4 = $xmlHandler->AppendNodeWithChild($root, "NodeLevel4", "Text4 - This node should be on same level like 3, 2 & 1, but instead it's a child of Level 3 (?!?!?!?!)");
echo "<p style='display:none;'>".$xmlHandler->SaveXml()."</p>";
?>

这是我用来创建xml请求结构的xml处理程序类(我只是在这里发布了类的必要部分)

XmlHandler.php:

<?php 
class XmlHandler{

    private $xml;
    /**
     *
     *    Constructor
     *
     */
    function __construct()
    {
        $this->xml=null;
    }
    //[...]
    /*
    *   Custom XML-Creator Functions 
    *
    */
    public function CreateNewXmlInstance(){
        /*********************************************/
        /** XML DOM example of building XML Request **/
        /*********************************************/
        $this->xml = new DOMDocument('1.0', 'UTF-8');
        return $this->xml;
    }
    public function CreateRootNode($name){
        $rootElement = $this->xml->appendChild( $this->xml->createElement($name) );
        return $rootElement;
    }
    public function AppendNodeWithChild($node, $childName, $childText){
        $result = $node->appendChild($this->xml->createElement($childName));
        if(null != $childText && !empty($childText)){
            $result->appendChild( $this->xml->createTextNode($childText) );
        }
        return $result;
    }
    public function SetNodeAttributes($node, $nameAndValues){
        if(null != $nameAndValues && sizeof($nameAndValues) > 0){
            foreach($nameAndValues as $name => $value){
                $this->SetNodeAttribute($node, $name, $value);
            }
        }
    }
    public function SetNodeAttribute($node, $name, $value){
        $node->setAttribute($name, $value);
    }
    public function SaveXml(){
        return $this->xml->saveXML();
    }
    //[...]
}
?>

这是结果:

<!-- ?xml version="1.0" encoding="UTF-8"? -->
<rootnode>
    <nodelevel1>Text1 - This node one has text</nodelevel1>
    <nodelevel2>Text2 - Next node Level3 level is not gonna have text
        <nodelevel2_1>Text2_1 - This node will be a child of Level2, everything fine</nodelevel2_1>
    </nodelevel2>
    <nodelevel3>
        <nodelevel4>Text4 - This node should be on same level like 3, 2 &amp; 1, but instead it's a child of Level 3 (?!?!?!?!)</nodelevel4>
    </nodelevel3>
</rootnode>

但理论上,应该有这样的东西:

<!-- ?xml version="1.0" encoding="UTF-8"? -->
<rootnode>
    <nodelevel1>Text1 - This node one has text</nodelevel1>
    <nodelevel2>Text2 - Next node Level3 level is not gonna have text
        <nodelevel2_1>Text2_1 - This node will be a child of Level2, everything fine</nodelevel2_1>
    </nodelevel2>
    <nodelevel3/>
    <nodelevel4>Text4 - This node should be on same level like 3, 2 &amp; 1, but instead it's a child of Level 3 (?!?!?!?!)</nodelevel4>
</rootnode>

正如你所看到的:当我没有为Level3上新创建的节点设置值时,出现了问题!:

$l3 = $xmlHandler->AppendNodeWithChild($root, "NodeLevel3", "");
$l4 = $xmlHandler->AppendNodeWithChild($root, "NodeLevel4", "Text4 - This node should be on same level like 3, 2 & 1, but instead it's a child of Level 3 (?!?!?!?!)");

只要在新创建的节点中设置属性或输入值,一切都很好。但我也有一些情况下,纯空节点必须创建!

我的问题是

我在这里做错了什么?

还是PHP做错了什么?

也许我的浏览器对XML的准备不好,但是发出的XML请求是正确构建和发送的,错误在于其他东西?

如果是这样,我如何检查XML请求?

编辑Nr.2:

我改变了我的问题/原来的帖子。上面的例子更容易理解。至少我希望如此。

将辅助函数包装在一个类中

class XMLHelper {
    /*
    *   Custom XML-Creator Functions
    *
    */
    private $xml;
    public function CreateNewXmlInstance(){
        /*********************************************/
        /** XML DOM example of building XML Request **/
        /*********************************************/
        $this->xml = new DOMDocument('1.0', 'UTF-8');
        return $this->xml;
    }
    public function CreateRootNode($name){
        $rootElement = $this->xml->appendChild( $this->xml->createElement($name) );
        return $rootElement;
    }
    public function AppendNodeWithChild($node, $childName, $childText){
        $result = $node->appendChild($this->xml->createElement($childName));
        if(null != $childText && !empty($childText)){
            $result->appendChild( $this->xml->createTextNode($childText) );
        }
        return $result;
    }
    public function SetNodeAttributes($node, $nameAndValues){
        if(null != $nameAndValues && sizeof($nameAndValues) > 0){
            foreach($nameAndValues as $name => $value){
                $this->SetNodeAttribute($node, $name, $value);
            }
        }
    }
    public function SetNodeAttribute($node, $name, $value){
        $node->setAttribute($name, $value);
    }
    public function SaveXml(){
        return $this->xml->saveXML();
    }
}

在类中包装东西,因为你的代码包含$this调用

在类中包装东西使$this调用来纠正程序需要的变量。

然后新建类并初始化节点

$test = new XMLHelper();
$test->CreateNewXmlInstance();
$request = $test->CreateRootNode("request");
$node1 = $test->AppendNodeWithChild($request, "node1", null);
$node2 = $test->AppendNodeWithChild($node1, "node2", null);
$test->SetNodeAttributes($node2, array(
    "client" => "This is a testing value"
));
echo $test->saveXml();
//Output: 
//    <?xml version="1.0" encoding="UTF-8"?>
//    <request>
//        <node1>
//            <node2 client="This is a testing value"/>
//        </node1>
//    </request>

请注意,代码需要按正确的顺序执行。

  1. 新建根节点(请求)
  2. 然后添加节点1到(请求)
  3. 最后将节点2附加到节点1
  4. 配置节点2的客户端值
  5. 打印整个根节点
  6. 那么你已经完成了魔法

PHP和你的浏览器都没有问题。

这个错误可能是由于您没有初始化根节点,并且没有正确地将创建的节点添加到根节点

关于php中的XML验证,请参见此链接。

DOMDocument有一个内置的验证函数。

编辑2016-08-10

这是修改后的箱子代码

class SpecificXmlHandler extends XmlHandler{
    /**
     *    Constructor
     *
     */
    private $errorCounter;
    private $xmlUrl;
    //Declare the root first
    private $root;
    function __construct()
    {
        parent::__construct();
        $this->errorCounter=0;
        $this->xmlUrl=Configuration::XML_REQUEST_URL;
    }

    //[...]
    /**
     *   Action Functions
     */
    public function GetStaticData($requestName, $requestFilterNamesAndValues){
        $xml = $this->BuildStaticDataRequest($requestName, $requestFilterNamesAndValues);
        echo "<p style='display:none'>" . $xml. "</p>";     //Request
        $response = $this->ExecuteRequest($this->xmlUrl, $xml, null, false);
        echo "<p style='display:none'>" . $response . "</p>"; //Resonse
        //[...]
    }
    //[...]
    /**
    *   Request Building Functions
    */
    public function BuildStaticDataRequest($requestName, $requestFilterNamesAndValues){
        $this->CreateNewXmlInstance();
        //$root = $this->CreateRootNode('Request');
        //Use the root node you have created in the constructor by using $this
        $this->root = $this->CreateRootNode('Request');
        //Generate Header (Source-Node)
        $this->GenerateHeadData($this->root);
        //[...]
        return $this->SaveXml();
    }
    public function GenerateHeadData($root){
        $clientID=Configuration::XML_CLIENT;

        //Here the Node1 & Node2 creation
        $node1 = $this->AppendNodeWithChild($root, "node1", null);
        $node2 = $this->AppendNodeWithChild($node1, "node2", null);
        $this->SetNodeAttributes( $node2 , array(
            "Client" =>$clientID
        ));
        //Change it to return the whole root
        return $root;
    }
[...]

}

请在类中创建变量,并使用$this来引用您创建的私有变量

好了,伙计们,有人帮我解决了这个问题。下面是对话:

Him:标签是错误的(因为它们已经改为全小写)

Me:是的,在回显到到浏览器而不是将保存到文件之后,XML似乎变得混乱了!

Him:输出甚至不应该格式化

Me:我自己做的,为了更好的看

Him:这是启用格式化输出后$xmlHandler->SaveXml()的原始输出

<?xml version="1.0" encoding="UTF-8"?>
<RootNode>
  <NodeLevel1>Text1 - This node one has text</NodeLevel1>
  <NodeLevel2>Text2 - Next node Level3 level is not gonna have text<NodeLevel2_1>Text2_1 - This node will be a child of Level2, everything fine</NodeLevel2_1></NodeLevel2>
  <NodeLevel3/>
  <NodeLevel4>Text4 - This node should be on same level like 3, 2 &amp; 1, but instead it's a child of Level 3 (?!?!?!?!)</NodeLevel4>
</RootNode>

Me:打印到文件后,我得到了与您相同的结果。

结论:

现在我已经将savxml输出写入了一个文件。结果与告诉我的一样。

那么混乱在哪里?

我认为用echo将XML打印到浏览器中并通过FireFox检查html源代码就足够了。

正如你在我的第一篇文章中看到的,我使用了echo…

echo "<p style='display:none;'>".$xmlHandler->SaveXml()."</p>";

以某种方式打印出xml创建的结果(因为我不知道还能怎么做)。

因此,xml创建是一个完整的成功,从启动和错误我得到的响应服务器位于其他地方(从现在开始,我不能再依赖你的帮助)!