【问题标题】:Remove Duplicate Namespaces from XML in Java从 Java 中的 XML 中删除重复的命名空间
【发布时间】:2017-08-01 02:05:56
【问题描述】:

我有以下肥皂响应作为示例:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:mycompany:Service:2" xmlns:urn1="urn:mycompany:Customer:2">
  <soapenv:Header />
  <soapenv:Body>
    <urn:GetResponse>
      <urn:StatusCode>002</urn:StatusCode>
      <urn:StatusMessage>Pass</urn:StatusMessage>
      <urn:CustomerAffiliations>
        <urn:CustomerAffiliation>
          <urn:CustomerID>II39642</urn:CustomerID>
          <urn:CustomerContactDetails>
            <ns3:Channel xmlns:ns3="urn:mycompany:Customer:2">Business Phone</ns3:Channel>
            <ns3:Value xmlns:ns3="urn:mycompany:Customer:2">5553647</ns3:Value>
          </urn:CustomerContactDetails>
        </urn:CustomerAffiliation>
      </urn:CustomerAffiliations>
    </urn:GetResponse>
  </soapenv:Body>
</soapenv:Envelope>

urn:mycompany:Customer:2 已作为 urn1 包含在 soapenv:Envelope 中,但在 ns3:Channelns3:Value 中重复。

要求是清理 xml 内容,以便在子元素中使用 soapenv:Envelope 中声明的正确命名空间。

Java 中是否有办法清理/规范化此 xml 内容并使用正确的命名空间使用和重复删除?

【问题讨论】:

标签: java xml dom jdom jdom-2


【解决方案1】:

以下代码将仅将“重复”命名空间替换为其继承的元素版本(属性也可以有自己的命名空间)......

请注意,这有一些可怕的时间复杂性,因此对于较大的 XML 文档,这可能会非常严重地退化......所以不要在深度嵌套或大于几百个元素的文档中使用它......在某些情况下指出时间复杂度会咬你。

另一方面,对于像您的 SOAP 示例这样的小数据包,这将绰绰有余...

private static final Namespace findFirst(List<Namespace> namespaces, String uri) {
    for (Namespace ns : namespaces) {
        if (ns.getURI().equals(uri)) {
            return ns;
        }
    }
    return null;
}


public static final void dedupElementNamespaces(Element node) {
    List<Namespace> created = node.getNamespacesIntroduced();
    if (!created.isEmpty()) {
        // check anything new against other stuff...
        List<Namespace> inherited = node.getNamespacesInherited();
        // check out element against previous declarations....
        if (node.getNamespace().getPrefix() != "") {
            // never swap defaulted namespaces to anything with a prefix.
            Namespace ens = node.getNamespace();
            Namespace use = findFirst(inherited, node.getNamespaceURI());
            if (use != null && use != ens) {
                node.setNamespace(use);
            }
        }           

    }
    for (Element e : node.getChildren()) {
        dedupElementNamespaces(e);
    }
}

你可以这样称呼它:

dedupElementNamespaces(doc.getRootElement());

node.getNamespacesIntroduced()node.getNamespacesInherited() 方法通过向上扫描 XML 层次结构来动态计算列表...因此它们的性能取决于嵌套的深度。见https://github.com/hunterhacker/jdom/blob/master/core/src/java/org/jdom2/Element.java#L1753

【讨论】:

  • findFirst方法的实现有什么想法吗?方法是做什么的?
  • 嗯...不知道为什么我第一次错过了复制该代码。不复杂,我这里加了。
猜你喜欢
  • 2011-02-26
  • 1970-01-01
  • 2020-12-03
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多