Я генерирую файл XML из многих источников. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что я передаю новый XML из веб-службы Soap и из других файлов XML, которые создаются другим приложением. Поскольку xml из веб-службы возвращается с префиксом пространства имен, мне нужно удалить префикс из веб-службы soap или получить префикс пространства имен из веб-службы soap и добавить его в XML-файл, созданный другим приложением.
Например, из мыльного веб-сервиса:
<s:element1></s:element1>
Из другого приложения:
<element2></element2>
И мне нужно создать xml следующим образом:
<element1></element1>
<element2></element2>
или же
<s:element1></s:element1>
<s:element2></s:element2>
Я думаю, что первый подход будет проще.
Я думал об использовании регулярных выражений, но не уверен, почему это звучит не очень хорошо для меня.
Я использую XPath для создания нового сгенерированного файла XML.
Спасибо!
Нет, вам не нужно удалять или изменять префиксы пространства имен. Пространства имен важны, префиксы — нет. Они просто псевдонимы, которые упрощают чтение 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)
Других решений пока нет …