PHP& XML Creation:错误的父节点

时间:2016-08-09 01:32:03

标签: php xml oop soap domdocument

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

现在,使用 DOMDocument 创建XML结构时遇到了一个大问题。 每当我创建一个没有属性的新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-Request-Structure的XML-Handler类(我刚刚在这里发布了该类的必要部分)

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:

我以某种方式更改了我的问题/原帖。 上面的例子有点容易理解。 至少我希望如此。

2 个答案:

答案 0 :(得分:0)

将帮助函数包装在类中

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. 然后你已经完成了魔法
  7. 使用您的网络浏览器,PHP没有任何问题。

    错误可能来自您尚未初始化根节点而未将正确创建的节点正确添加到根节点

    对于php中的XML验证,请参阅this link

    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来引用您创建的私有变量。

答案 1 :(得分:0)

好的,有人帮我解决了这个问题。 这是对话:

他:标签错误(因为它们已被更改为全小写)

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

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

我:我自己这样做是为了更好的观点

他:这是启用格式化输出后$ xmlHandler-&gt; 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>

我: 打印后,将其输入文件,我得到的结果与您相同。

结论:

现在我已将saveXml-output写入文件。 结果与告诉我的结果相同。

那是一团糟吗?

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

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

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

以某种方式打印出我的XML-Creation的结果(因为我不知道如何)。

因此,XML-Creation从启动就取得了圆满成功,我从响应服务器获得的错误位于其他地方(从现在开始,我不能再依靠你的帮助了)!