我目前正在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 & 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 & 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
- 配置节点2的客户端值
- 打印整个根节点
- 那么你已经完成了魔法
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 & 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创建是一个完整的成功,从启动和错误我得到的响应服务器位于其他地方(从现在开始,我不能再依赖你的帮助)!