使用xslt为元素和子节点添加名称空间前缀

时间:2014-06-26 14:22:38

标签: xslt xslt-1.0 xslt-2.0

我想复制所有子节点的 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“属性添加到标题子节点。感谢任何帮助

2 个答案:

答案 0 :(得分:2)

这是我的(编辑过的)建议:

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

答案 1 :(得分:2)

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

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

将源与此样式表一起使用(评论中说明的模板):

<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 ,您可以在其中查看结果。