Простой DOMDocument и добавление двух дочерних узлов, один без и один с пространством имен по умолчанию:
$dom = new DOMDocument();
$dom->loadXML('<list/></list>');
$dom->formatOutput = true;
$docX = new DOMDocument();
$docX->loadXML('<item><one>bar</one></item>');
$dom->documentElement->appendChild($dom->importNode($docX->documentElement, true));
print($dom->saveXML()); // OK
$docY = new DOMDocument();
$docY->loadXML('<item><two xmlns="xxx:yyy">tar</two></item>');
$dom->documentElement->appendChild($dom->importNode($docY->documentElement, true));
print($dom->saveXML()); // Not OK
Добавление дочернего узла без атрибута xmlns
работает нормально:
<?xml version="1.0"?>
<list>
<item>
<one>bar</one>
</item>
</list>
При добавлении дочернего узла с пространством имен по умолчанию (т. Е. Атрибут xmlns
) PHP добавляет псевдоним default
для этого пространства имен:
<?xml version="1.0"?>
<list>
...
<item xmlns:default="xxx:yyy">
<default:two xmlns="xxx:yyy">tar</default:two>
</item>
</list>
Я никогда не видел его в своем коде 15+ летв PHP.Есть ли рекомендуемый обходной путь, чтобы избежать такого поведения?
В гораздо более сложном сценарии я пытался просто установить для этого префикса значение null после вызова appendChild()
, но он выдает загадочное сообщение DOMException: Namespace Error
.Этот упрощенный пример этого не делает, вместо этого он генерирует следующий XML:
<?xml version="1.0"?>
<list>
...
<item xmlns:default="xxx:yyy">
<:two xmlns="xxx:yyy" xmlns:="xxx:yyy">tar</:two>
</item>
</list>
В качестве обходного пути после добавления дочернего элемента я клонирую его, удаляя все пространства имен префиксов в процессе, удаляя исходный дочерний элемент.вместо добавления клона (префикса default
нет) и повторного добавления префиксов, где:
function stripNamespace($dom, $target) {
$clone = $dom->createElement(preg_replace('`.*:`', '', $target->nodeName));
foreach ($target->attributes as $v)
$clone->setAttribute($v->nodeName, $v->value);
foreach ($target->childNodes as $child)
$clone->appendChild(
$child->nodeName == "#text" ?
$dom->createTextNode($child->nodeValue) :
$this->stripNamespace($dom, $child)
);
return $clone;
}
Есть ли менее громоздкий способ справиться с этим?