【问题标题】:Duplicate xml namespace declarations php DOMDocument重复的xml命名空间声明php DOMDocument
【发布时间】:2019-03-25 01:33:48
【问题描述】:

我使用 PHP DOMDocument 来生成 xml。有时命名空间仅在根元素上声明,这是预期的行为,但有时不是。 例如:

$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");

我希望:

<?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" 的声明出现在Document 元素上,而不出现在&lt;innerElement&gt; 中?以及如何防止重复?

【问题讨论】:

    标签: php xml domdocument


    【解决方案1】:

    这很容易。只需将您的节点添加到文档树中。 此外,您可以在根节点中显式创建 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>
    

    【讨论】:

    • 还请注意,DOMDocument 足够聪明,因此如果您已经声明了命名空间,则无需调用 createElementNS()。在我的示例中,我只使用带有完全限定元素名称的 createElement()。
    • 你错了 - 它只序列化为相同的 XML 字符串。但是元素节点是在命名空间之外创建的。在将其保存为 XML 之前输出其 $namespaceURI
    • 任务是简单地将 xml 序列化为没有 ns 重复的字符串。此任务已正确解决。那我为什么错了? ))
    • 评论有误。 DOMDocument 不够“聪明”。如果您使用带有完全限定元素名称的 createElement(),它不会解决命名空间 - 它会忽略它们。创建的节点不在命名空间中。只有在您序列化和解析 XML 之后,您才会拥有带有命名空间的有效节点。如果不只是创建+保存文档,而且有与创建的 DOM 一起使用的方法,这一点很重要。
    猜你喜欢
    • 2018-02-11
    • 2011-01-27
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    相关资源
    最近更新 更多