Search code examples
phpxmldomdocument

Duplicate xml namespace declarations php DOMDocument


I use PHP DOMDocument to generate xml. Sometimes namespaces are declared only on root element, which is intended behaviour, but sometimes no. For example:

$xml = new DOMDocument('1.0', 'utf-8');
$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");

I expect:

<?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>

But got:

<?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>

Why declaration of xmlns:ons="http://otherns.com" appears on Document element, but not in <innerElement>? And how to prevent duplicates?


Solution

  • It's very easy. Just add your nodes into document tree. Additionally you can explicitly create xmlns:XXX atrtribute in root node. See example:

    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();
    

    Result:

    <?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>