这就是我所追求的
<!-- language: lang-xml -->
<ws:Test>
<ws:somename2>somevalue2</ws:somename2>
<ws:make>
<ws:model>foo</ws:model>
<ws:model>bar</ws:model>
</ws:make>
</ws:Test>
Run Code Online (Sandbox Code Playgroud)
这是我目前的代码
<!-- language: lang-php -->
$xmlTest = new SimpleXMLElement('<Test/>', 0, false, 'ws', true);
$xmlTest->addChild("ws:somename2", "somevalue2", 'http://microsoft.com/wsdl/types/');
$make = $xmlTest->addChild('ws:make', null, 'ws');
#$make->addAttribute('name','Ford');
$make->addChild('ws:model', 'foo', 'ws');
$make->addChild('ws:model', 'bar', 'ws');
header ("Content-Type:text/xml");
print_r($xmlTest->asXML());
Run Code Online (Sandbox Code Playgroud)
但它输出
<!-- language: lang-xml -->
<Test>
<ws:somename2>somevalue2</ws:somename2>
<ws:make>
<ws:model>foo</ws:model>
<ws:model>bar</ws:model>
</ws:make>
</Test>
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,测试中缺少ws:
Kyr*_*ril 30
SimpleXML有一个不寻常的怪癖,其中名称空间前缀从根元素中过滤掉.我不确定为什么会这样做.
但是,我使用的解决方法基本上是前缀的前缀,以便解析器只删除第一个,然后留下第二个
$xmlTest = new SimpleXMLElement('<xmlns:ws:Test></xmlns:ws:Test>', LIBXML_NOERROR, false, 'ws', true);
$xmlTest->addAttribute('xmlns:xmlns:ws', 'http://url.to.namespace');
$xmlTest->addAttribute('xmlns:xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
Run Code Online (Sandbox Code Playgroud)
这似乎对我有用,虽然我有兴趣理解为什么SimpleXML会这样做.
IMS*_*SoP 10
这段代码的问题在第一行:
$xmlTest = new SimpleXMLElement('<Test/>', 0, false, 'ws', true);
Run Code Online (Sandbox Code Playgroud)
在做任何其他事情之前,让我们将其输出为XML:
echo $xmlTest->asXML();
<?xml version="1.0"?>
<Test/>
Run Code Online (Sandbox Code Playgroud)
这是有道理的,我们得到了我们投入的东西.
关于$ns论证的作用,手册相当模糊,但在这种情况下,它没有做任何有用的事情.它的作用是设置读取 XML 的上下文,以便->foo引用<ws:foo>和['bar']引用ws:bar="...".它没有做任何改变XML本身结构的事情.
要在根元素上设置命名空间,我们只需将它包含在定义根元素的字符串中:
$xmlTest = new SimpleXMLElement('<ws:Test xmlns:ws="http://microsoft.com/wsdl/types/" />');
echo $xmlTest->asXML();
<?xml version="1.0"?>
<ws:Test xmlns:ws="http://microsoft.com/wsdl/types/"/>
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好...
接下来,让我们理智地检查问题中的代码实际输出的内容(我添加了一些空格以使其更具可读性):
<?xml version="1.0"?>
<Test>
<ws:somename2 xmlns:ws="http://microsoft.com/wsdl/types/">somevalue2</ws:somename2>
<ws:make xmlns:ws="ws">
<ws:model>foo</ws:model>
<ws:model>bar</ws:model>
</ws:make>
</Test>
Run Code Online (Sandbox Code Playgroud)
好的,所以这个文档包含两个名称空间声明:
xmlns:ws="http://microsoft.com/wsdl/types/"在somename2元素上xmlns:ws="ws"在make元素上,然后由model元素继承如果我们添加更正的根元素会发生什么?
<?xml version="1.0"?>
<ws:Test xmlns:ws="http://microsoft.com/wsdl/types/">
<ws:somename2>somevalue2</ws:somename2>
<ws:make xmlns:ws="ws">
<ws:model>foo</ws:model>
<ws:model>bar</ws:model>
</ws:make>
</ws:Test>
Run Code Online (Sandbox Code Playgroud)
很酷,所以somename2元素现在从根元素继承其命名空间定义,并且不重新声明它.但是make和models 有什么不对?让我们比较一下:
$xmlTest->addChild("ws:somename2", "somevalue2", 'http://microsoft.com/wsdl/types/');
$make = $xmlTest->addChild('ws:make', null, 'ws');
Run Code Online (Sandbox Code Playgroud)
第三个参数应该是命名空间URI,而不仅仅是前缀.因此,当我们给它时'ws',SimpleXML假设我们想要将实际的名称空间URI声明为ws,所以添加了一个xmlns属性来执行此操作.
我们真正想要的是在同一名称空间中的所有元素:
$xmlTest = new SimpleXMLElement('<ws:Test xmlns:ws="http://microsoft.com/wsdl/types/" />');
$xmlTest->addChild("ws:somename2", "somevalue2", 'http://microsoft.com/wsdl/types/');
$make = $xmlTest->addChild('ws:make', null, 'http://microsoft.com/wsdl/types/');
#$make->addAttribute('name','Ford', 'http://microsoft.com/wsdl/types/');
$make->addChild('ws:model', 'foo', 'http://microsoft.com/wsdl/types/');
$make->addChild('ws:model', 'bar', 'http://microsoft.com/wsdl/types/');
echo $xmlTest->asXML();
<?xml version="1.0"?>
<ws:Test xmlns:ws="http://microsoft.com/wsdl/types/">
<ws:somename2>somevalue2</ws:somename2>
<ws:make>
<ws:model>foo</ws:model>
<ws:model>bar</ws:model>
</ws:make>
</ws:Test>
Run Code Online (Sandbox Code Playgroud)
太棒了,我们得到了我们想要的输出!
但是这段代码看起来很难看,为什么我们必须在任何地方重复URI?那么,就SimpleXML而言,没有太多选择:相同的前缀在文档的不同部分可能意味着不同的东西,所以我们必须告诉它我们想要什么.
我们可以做的是使用变量或常量为名称空间URI整理我们的代码,而不是每次都完整地写出来:
define('XMLNS_WS', 'http://microsoft.com/wsdl/types/');
$xmlTest = new SimpleXMLElement('<ws:Test xmlns:ws="' . XMLNS_WS . '" />');
$xmlTest->addChild("ws:somename2", "somevalue2", XMLNS_WS);
$make = $xmlTest->addChild('ws:make', null, XMLNS_WS);
#$make->addAttribute('name','Ford', XMLNS_WS);
$make->addChild('ws:model', 'foo', XMLNS_WS);
$make->addChild('ws:model', 'bar', XMLNS_WS);
Run Code Online (Sandbox Code Playgroud)
这里的名称没有什么特别之处XMLNS_WS,它同样可以是变量,类常量或命名空间常量.代码运行完全相同,只是稍微容易一点.