Я использую PHP DomDocument для создания xml. Иногда пространства имен объявляются только в корневом элементе, что является предполагаемым поведением, но иногда нет. Например:
$xml = new DOMDocument("1.0",$charset);
$ns = "http://ns.com";
$otherNs = "http://otherns.com";
$docs = $xml->createElementNS($ns,"ns:Documents");
$doc = $xml->createElementNS($otherNs, "ons:Document");
$innerElement = $xml->createElementNS($otherNs, "ons:innerElement", "someValue");
$doc->appendChild($innerElement);
$docs->appendChild($doc);
$xml->appendChild($docs);
$xml->formatOutput = true;
$xml->save("dom");
Я ожидаю:
<?xml version = "1.0" encoding = "UTF-8"?>
<ns:Documents xmlns:ns = "http://ns.com" xmlns:ons = "http://otherns.com">
<ons:Document>
<ons:innerElement>someValue</ons:innerElement>
</ons:Document>
</ns:Documents>
Но получил:
<?xml version = "1.0" encoding = "UTF-8"?>
<ns:Documents xmlns:ns = "http://ns.com" xmlns:ons = "http://otherns.com">
<ons:Document xmlns:ons = "http://otherns.com">
<ons:innerElement>someValue</ons:innerElement>
</ons:Document>
</ns:Documents>
Почему объявление xmlns: ons = "http://otherns.com" появляется в элементе Документ, а не в innerElement? А как предотвратить дублирование?






Это очень легко. Просто добавьте свои узлы в дерево документа. Кроме того, вы можете явно создать атрибут xmlns: XXX в корневом узле. См. Пример:
namespace test;
use DOMDocument;
$xml = new DOMDocument("1.0", "UTF-8");
$ns = "http://ns.com";
$otherNs = "http://otherns.com";
$docs = $xml->createElementNS($ns, "ns:Documents");
$xml->appendChild($docs);
$docs->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:ons', $otherNs);
$doc = $xml->createElement("ons:Document");
$docs->appendChild($doc);
$innerElement = $xml->createElement("ons:innerElement", "someValue");
$doc->appendChild($innerElement);
$xml->formatOutput = true;
echo $xml->saveXML();
Результат:
<?xml version = "1.0" encoding = "UTF-8"?>
<ns:Documents xmlns:ns = "http://ns.com" xmlns:ons = "http://otherns.com">
<ons:Document>
<ons:innerElement>someValue</ons:innerElement>
</ons:Document>
</ns:Documents>
Вы ошибаетесь - он сериализуется только в одну и ту же строку XML. Но узел элемента создается вне пространства имен. Перед сохранением в XML выведите его $namespaceURI.
Также обратите внимание, что DOMDocument достаточно умен, поэтому вам не нужно вызывать createElementNS (), если у вас уже объявлено пространство имен. В моем примере я просто использую createElement () с полным именем элемента.