从不同来源生成的混合 XML + PHP Xpath
Mixed XML generated from different sources + PHP Xpath
我正在从多个来源生成一个 XML 文件。我现在面临的问题是,我从 Soap Web 服务和另一个应用程序生成的另一个 XML 文件中提供新的 XML。由于来自 web 服务的 xml 返回时带有命名空间前缀,因此我需要从 soap web 服务中删除前缀或从 soap web 服务中获取命名空间前缀并将其添加到由生成的 XML另一个应用程序。
例如,来自 soap 网络服务:
<s:element1></s:element1>
来自其他应用程序:
<element2></element2>
我需要像这样生成 xml:
<element1></element1>
<element2></element2>
或
<s:element1></s:element1>
<s:element2></s:element2>
我认为第一种方法会更容易。
我正在考虑使用正则表达式,但不确定为什么它对我来说听起来不太好。
我正在使用 XPath 生成新的 XML 文件。
谢谢!
不,您不需要删除或更改名称空间前缀。命名空间很重要,前缀不重要。它们只是使 XML 更易于阅读的别名。
以下示例显示了 3 个不同的 xml,它们都解析为命名空间 urn:example
.
中具有本地名称 foo
的元素节点
$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)
我正在从多个来源生成一个 XML 文件。我现在面临的问题是,我从 Soap Web 服务和另一个应用程序生成的另一个 XML 文件中提供新的 XML。由于来自 web 服务的 xml 返回时带有命名空间前缀,因此我需要从 soap web 服务中删除前缀或从 soap web 服务中获取命名空间前缀并将其添加到由生成的 XML另一个应用程序。
例如,来自 soap 网络服务:
<s:element1></s:element1>
来自其他应用程序:
<element2></element2>
我需要像这样生成 xml:
<element1></element1>
<element2></element2>
或
<s:element1></s:element1>
<s:element2></s:element2>
我认为第一种方法会更容易。
我正在考虑使用正则表达式,但不确定为什么它对我来说听起来不太好。
我正在使用 XPath 生成新的 XML 文件。
谢谢!
不,您不需要删除或更改名称空间前缀。命名空间很重要,前缀不重要。它们只是使 XML 更易于阅读的别名。
以下示例显示了 3 个不同的 xml,它们都解析为命名空间 urn:example
.
foo
的元素节点
$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)