【问题标题】:Tweak XML namespace declaration styles in serialized DOM调整序列化 DOM 中的 XML 命名空间声明样式
【发布时间】:2018-01-17 14:12:05
【问题描述】:

请考虑作为对 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>

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

【问题讨论】:

    标签: java xml dom jax-ws


    【解决方案1】:

    你可以像这样在 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”而不是在默认命名空间中没有前缀。您需要进行一些进一步的调整才能改变这一点,因为我的代码会生成一个文档,其中给定命名空间中的所有元素都具有相同的前缀。我不知道为什么你应该优先考虑你的输出。 (事实上​​,说实话,我不知道这个小练习有什么意义。为什么会有人关心?)

    【讨论】:

    • 我使用 xsltproc 进行了测试,但在变量 p 评估时出现错误:`XPath 错误:无效类型运行时错误:文件 tx.xslt 第 12 行元素变量无法评估变量“p”的表达式。没有结果 wrong.xml``
    • 我的 XSLT 1.0 知识非常生疏。已更正。
    • 进行这种转换的原因是消费者(outlook 2016)似乎对命名空间的呈现方式非常挑剔。它不解析第一个,但正确处理第二个。显然我无法调整 Outlook 如何处理 EWS 调用。
    【解决方案2】:

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

    这对我来说是正确的。

    【讨论】:

    • 这是正确的,当然,但是由于 OP 对命名空间前缀很挑剔,所以它不会产生他们要求的输出。
    猜你喜欢
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多