在序列化 DOM 中调整 XML 命名空间声明样式

Tweak XML namespace declaration styles in serialized DOM

请考虑作为对 SOAP 调用的响应而生成的两个等效 xml 文档。

文件一:

<?xml version="1.0" encoding="utf-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Header>
    <ns2:ServerVersionInfo xmlns:ns3="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:ns2="http://schemas.microsoft.com/exchange/services/2006/types" MajorVersion="15" MinorVersion="1" MajorBuildNumber="845" MinorBuildNumber="34"/>
  </S:Header>
  <S:Body>
    <ns3:GetUserAvailabilityResponse xmlns:ns3="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:ns2="http://schemas.microsoft.com/exchange/services/2006/types">
      <ns3:FreeBusyResponseArray>
        <ns3:FreeBusyResponse>
          <ns3:ResponseMessage ResponseClass="Success">
            <ns3:ResponseCode>NoError</ns3:ResponseCode>
          </ns3:ResponseMessage>
          <ns3:FreeBusyView>
            <ns2:FreeBusyViewType>MergedOnly</ns2:FreeBusyViewType>
            <ns2:MergedFreeBusy>0000</ns2:MergedFreeBusy>
          </ns3:FreeBusyView>
        </ns3:FreeBusyResponse>
      </ns3:FreeBusyResponseArray>
    </ns3:GetUserAvailabilityResponse>
  </S:Body>
</S:Envelope>

文件二:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" MajorVersion="15" MinorVersion="1" MajorBuildNumber="845" MinorBuildNumber="34"/>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <GetUserAvailabilityResponse xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
      <FreeBusyResponseArray>
        <FreeBusyResponse>
          <ResponseMessage ResponseClass="Success">
            <ResponseCode>NoError</ResponseCode>
          </ResponseMessage>
          <FreeBusyView>
            <FreeBusyViewType xmlns="http://schemas.microsoft.com/exchange/services/2006/types">MergedOnly</FreeBusyViewType>
            <MergedFreeBusy xmlns="http://schemas.microsoft.com/exchange/services/2006/types">0000</MergedFreeBusy>
          </FreeBusyView>
        </FreeBusyResponse>
      </FreeBusyResponseArray>
    </GetUserAvailabilityResponse>
  </s:Body>
</s:Envelope>

如果我错了请纠正我,但那些 DOM 看起来在语义上相似,除了 xml 命名空间声明样式。我想从文档一的样式到文档二的样式调整我的 java 应用程序的 jax-ws 输出。 如有必要,我可以用 javax.xml.transform.Transformer 重新处理 DOM。

您可以像这样在 XSLT 中执行此操作:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    
<xsl:variable name="bindings">
      <ns prefix="s:" uri="http://schemas.xmlsoap.org/soap/envelope/"/>
      <ns prefix="h:" uri="http://schemas.microsoft.com/exchange/services/2006/types"/>
      <ns prefix="" uri="http://schemas.microsoft.com/exchange/services/2006/messages"/>
    </xsl:variable>

    <xsl:template match="*">
      <xsl:variable name="p" select="$bindings/ns[@uri=namespace-uri(current())]/@prefix"/>
      <xsl:element name="{$p}{local-name()}" namespace="{namespace-uri()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
      </xsl:element>
    </xsl:template>
</xsl:transform>

现已测试(虽然未使用 xsltproc)。

除了 FreeBusyViewType 和 MergedFreeBusy 使用命名空间前缀 "h" 而不是在默认命名空间中取消前缀外,它提供了 "Document two" 的输出。您需要做一些进一步的调整才能改变它,因为我的代码生成了一个文档,其中给定名称空间中的所有元素都具有相同的前缀。我不知道为什么你应该优先考虑你的输出。 (事实上​​ ,老实说,我不知道这个小练习的意义是什么。为什么会有人关心?)

@mickael-kay 的回答几乎是正确的。以下样式表进行了正确的转换:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="*">
    <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

并且当 运行 与 xsltproc 给出以下结果时:

<?xml version="1.0"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Header>
    <ServerVersionInfo xmlns="http://schemas.microsoft.com/exchange/services/2006/types" MajorVersion="15" MinorVersion="1" MajorBuildNumber="845" MinorBuildNumber="34"/>
  </Header>
  <Body>
    <GetUserAvailabilityResponse xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
      <FreeBusyResponseArray>
        <FreeBusyResponse>
          <ResponseMessage ResponseClass="Success">
            <ResponseCode>NoError</ResponseCode>
          </ResponseMessage>
          <FreeBusyView>
            <FreeBusyViewType xmlns="http://schemas.microsoft.com/exchange/services/2006/types">MergedOnly</FreeBusyViewType>
            <MergedFreeBusy xmlns="http://schemas.microsoft.com/exchange/services/2006/types">0000</MergedFreeBusy>
          </FreeBusyView>
        </FreeBusyResponse>
      </FreeBusyResponseArray>
    </GetUserAvailabilityResponse>
  </Body>
</Envelope>

这对我来说是正确的。