【问题标题】:add namespace prefix to element and subnodes with xslt使用 xslt 为元素和子节点添加命名空间前缀
【发布时间】:2014-08-17 10:56:59
【问题描述】:

我想复制 only header 元素和所有子节点并添加到每个子节点前缀“v11”(包括标题元素)

来源 xml:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns3:createReservationRequest xmlns:ns3="ns3URL" xmlns:ns2="ns2URL">
            <header>
                <language isoCountryCode="US" isoLanguageCode="en"/>
                <channel name="DT">
                    <subChannel name="WEBWB">
                        <subChannel name="WEBWB">
                            <subChannel name="Functester">
                                <subChannel name="ecom"/>
                            </subChannel>
                        </subChannel>
                    </subChannel>
                </channel>
            </header>
            <ns3:agentInfo>
                <ns2:agentDutyCode>PR</ns2:agentDutyCode>
            </ns3:agentInfo>
        </ns3:createReservationRequest>
    </soap:Body>
</soap:Envelope>

所需的结果 xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:v1="v1URL"
              xmlns:v11="v11URL">
    <soapenv:Body>
        <v1:createBookerEventRequest>
            <v11:header>
                <v11:channel name="DT">
                    <v11:subChannel name="WEBWB">
                        <v11:subChannel name="WEBWB">
                            <v11:subChannel name="Functester">
                                <v11:subChannel name="ecom"/>
                            </v11:subChannel>
                        </v11:subChannel>
                    </v11:subChannel>
                </v11:channel>
            </v11:header>
        </v1:createBookerEventRequest>
    </soapenv:Body>
</soapenv:Envelope>

我尝试使用来自 here 的示例来实现这一点。我写了以下xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:v11="v11URL">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <xsl:copy>
            <xsl:apply-templates select="//*[local-name()='header']/*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//*[local-name()='header']/*">
        <xsl:element name="v11:{name()}" inherit-namespaces="no">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

但它不会将子通道复制到结果 xml 中。并且还向标头子节点添加了不需要的“xmlns:v11="http://example.com/schema/common/ATPCommonServiceTypes/v1”属性。感谢任何帮助

【问题讨论】:

  • 请发布一个命名空间格式良好的 XML 输入示例,目前 ns2:agentDutyCode 有一个未声明的前缀。
  • 并且根元素没有关闭。

标签: xslt xslt-1.0 xslt-2.0


【解决方案1】:

这是我的(修改后的)建议:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:v1="v1URL"
            xmlns:v11="v11URL"
            xmlns:ns3="ns3URL"
            exclude-result-prefixes="soap ns3">

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="/*">
  <xsl:copy>
    <xsl:copy-of select="document('')/xsl:stylesheet/namespace::*[local-name() = ('v1', 'v11')]"/>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="*[not(namespace-uri())]">
  <xsl:element name="v11:{local-name()}">
    <xsl:apply-templates select="@* , node()"/>
  </xsl:element>
</xsl:template>

<xsl:template match="ns3:createReservationRequest">
  <v1:createBookerEventRequest>
    <xsl:apply-templates select="@* , node()"/>
  </v1:createBookerEventRequest>
</xsl:template>

<xsl:template match="ns3:agentInfo"/>

</xsl:stylesheet>

【讨论】:

    【解决方案2】:

    我向agentDutyCode 添加了xmlns 声明,因为它缺少命名空间声明:

    <ns2:agentDutyCode xmlns:ns2="ns2URL">PR</ns2:agentDutyCode>
    

    使用带有此样式表的源代码(在 cmets 中解释了模板):

    <xsl:stylesheet version="2.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:v11="v11URL"
        xmlns:v1="v1URL"
        xmlns:ns3="ns3URL"
        exclude-result-prefixes="ns3">
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
        <xsl:strip-space elements="*"/>
    
        <!-- Copies Envelope and Body preserving their namespace -->
        <xsl:template match="soap:Envelope | soap:Body">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <!-- Creates the createReservationRequest element -->
        <xsl:template match="ns3:createReservationRequest">
            <v1:createBookerEventRequest>
                <xsl:apply-templates/>
            </v1:createBookerEventRequest>
        </xsl:template>
    
        <!-- Ignores language and agentInfo subtrees -->
        <xsl:template match="language"/>
        <xsl:template match="ns3:agentInfo"/>
    
        <!-- Matches all other elements -->
        <xsl:template match="*">
            <xsl:element name="v11:{local-name()}" inherit-namespaces="no">
                <xsl:apply-templates select="node()|@*"/>
            </xsl:element>
        </xsl:template>
    
        <!-- Copies attributes -->
        <xsl:template match="@*">
            <xsl:copy>
                <xsl:value-of select="."/>
            </xsl:copy>
        </xsl:template>
    
    </xsl:stylesheet>
    

    你会得到这样的结果:

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body>
          <v1:createBookerEventRequest xmlns:v11="v11URL" xmlns:v1="v1URL">
             <v11:header>
                <v11:channel name="DT">
                   <v11:subChannel name="WEBWB">
                      <v11:subChannel name="WEBWB">
                         <v11:subChannel name="Functester">
                            <v11:subChannel name="ecom"/>
                         </v11:subChannel>
                      </v11:subChannel>
                   </v11:subChannel>
                </v11:channel>
             </v11:header>
          </v1:createBookerEventRequest>
       </soap:Body>
    </soap:Envelope>
    

    这是一个 XSLT Fiddle,您可以在其中看到结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多