从不同来源+ PHP Xpath生成的混合XML

时间:2015-12-28 01:46:14

标签: php xml file xpath generated

我从许多来源生成XML文件。我现在面临的问题是我从Soap Webservice和另一个应用程序生成的另一个XML文件中提供新的XML。由于webservice中的xml返回了一个名称空间前缀,我需要从soap webservice中删除前缀或从soap webservice获取名称空间前缀,并将其添加到由其他应用程序生成的XML中。

例如,来自soap webservice:

   commands = new Command[]
            {          
                 new Value 
                {

                    Value = CreatedOn.HasValue ? ((DateTime)CreatedOn.Value).ToLongDateString() : "",  
                    LinkedCommand = SOSchema.SpecifyShipmentParameters.ShipmentDate, 
                    Commit = true 
                },
                new Value 
                {

                    Value = "OK", 
                    LinkedCommand = SOSchema.SpecifyShipmentParameters.ServiceCommands.DialogAnswer, 
                    Commit = true 
                },               
                SOSchema.Actions.ActionCreateReceipt
            };
                context.SO301000Submit(commands);

来自其他应用程序:

<s:element1></s:element1>

我需要像这样生成一个xml:

<element2></element2>

<element1></element1>
<element2></element2>

我认为第一种方法会更容易。

我正在考虑使用正则表达式,但不确定为什么它对我来说听起来不太好。

我使用XPath制作新生成的XML文件。

谢谢!

1 个答案:

答案 0 :(得分:1)

不,您不需要删除或更改名称空间前缀。命名空间很重要,前缀不重要。它们只是别名,使XML更易于阅读。

以下示例显示了3个不同的xmls,它们都解析为名称空间foo中具有本地名称urn:example的元素节点。

$xmls = [
  '<f:foo xmlns:f="urn:example"/>',
  '<bar:foo xmlns:bar="urn:example"/>',
  '<foo xmlns="urn:example"/>'
];

foreach ($xmls as $xml) {
  $document = new DOMDocument();
  $document->loadXml($xml);
  var_dump(
    $document->documentElement->localName,
    $document->documentElement->namespaceURI
  );
}

输出:

string(3) "foo"
string(11) "urn:example"
string(3) "foo"
string(11) "urn:example"
string(3) "foo"
string(11) "urn:example"

因此,每个节点都有可用的信息。如果将一个节点导入到一个文档中,它将带有它的命名空间,并保留信息。

$xmls = [
  '<f:foo xmlns:f="urn:example"/>',
  '<bar:foo xmlns:bar="urn:example"/>',
  '<foo xmlns="urn:example"/>'
];

$target = new DOMDocument();
$target->loadXml('<f:foo xmlns:f="urn:example"/>');

foreach ($xmls as $xml) {
  $document = new DOMDocument();
  $document->loadXml($xml);
  $xpath = new DOMXpath($document);
  $xpath->registerNamespace('e', 'urn:example');
  $target->documentElement->appendChild(
    $target->importNode($xpath->evaluate('/e:foo')->item(0), TRUE)
  );
}

echo $target->saveXml(), "\n\n";

输出:

<?xml version="1.0"?>
<f:foo xmlns:f="urn:example"><f:foo/><bar:foo xmlns:bar="urn:example"/><f:foo/></f:foo>

对于Xpath,您必须为命名空间注册自己的前缀。这可以是与文档中相同的前缀或不同的前缀。如果正确完成,文档中的名称空间前缀不相关:

$xpath = new DOMXpath($target);
$xpath->registerNamespace('e', 'urn:example');
var_dump($xpath->evaluate('count(//e:foo)'));

输出:

float(4)