如何使用xslt删除命名空间并更新输出元素

时间:2014-10-30 08:38:26

标签: xslt cdata

我有一个XML元素需要使用XSLT转换为另一种形式。我在下面发布了请求和响应xml。我是XSLT的新手,需要帮助将请求转换为响应格式。

请求:

<p:ReservationRequest xmlns:p="http://sample.request.com/">
      <!--Exactly 1 occurrence-->
      <p:Reservation>
         <p:tktReservationGUID>13579</p:tktReservationGUID>
         <p:tktState>CA</p:tktState>
         <p:LocationId>1357</p:LocationId>
      </p:Reservation>
   </p:ReservationRequest>

响应:

  <tem:SendReservation xmlns:tem="http://tempuri.org/">
     <!--Optional:-->
     <tem:ProviderGuid xmlns:tem="http://tempuri.org/">1111</tem:ProviderGuid>
     <!--Optional:-->
     <tem:Username xmlns:tem="http://tempuri.org/">usertext</tem:Username>
     <!--Optional:-->
     <tem:Password xmlns:tem="http://tempuri.org/">passtext</tem:Password>
     <!--Optional:-->
     <tem:Data><![CDATA[<DATA> <Reservation>

     <tktReservationGUID>54321</tktReservationGUID>
     <tktState>CA</tktState>
     <LocationId>1357</LocationId>
  </Reservation> </DATA>]]></tem:Data>
  </tem:SendReservation>

我需要从请求元素中剥离命名空间,并在将另一个主元素“DATA”附加到请求元素之后,在“tem:DATA”下的响应中使用CDATA附加它们。

我非常感谢您在使用XSLT将以下请求转换为已发布的响应方面的任何帮助。

此致 Rudraksh

2 个答案:

答案 0 :(得分:2)

假设使用XSLT 3.0和Saxon 9.6,您可以使用serialize函数将转换后的临时树转换为标记:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:p="http://sample.request.com/"
  xmlns:tem="http://tempuri.org/"
  exclude-result-prefixes="p tem"
  version="3.0">

<xsl:output indent="yes" cdata-section-elements="tem:Data" omit-xml-declaration="yes"/>

<xsl:template match="/">
  <tem:SendReservation xmlns:tem="http://tempuri.org/">
     <!--Optional:-->
     <tem:ProviderGuid xmlns:tem="http://tempuri.org/">1111</tem:ProviderGuid>
     <!--Optional:-->
     <tem:Username xmlns:tem="http://tempuri.org/">usertext</tem:Username>
     <!--Optional:-->
     <tem:Password xmlns:tem="http://tempuri.org/">passtext</tem:Password>
     <!--Optional:-->
     <tem:Data>
       <xsl:variable name="data">
         <DATA>
           <xsl:apply-templates select="p:ReservationRequest"/>
         </DATA>
       </xsl:variable>
       <xsl:variable name="ser-params">
          <output:serialization-parameters
                 xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
            <output:indent value="yes"/>
            <output:version value="1.0"/>
            <output:method value="xml"/>
            <output:omit-xml-declaration value="yes"/>
          </output:serialization-parameters>
       </xsl:variable>
       <xsl:value-of select="serialize($data/*, $ser-params/*)"/>
     </tem:Data>
   </tem:SendReservation>
</xsl:template>

<xsl:template match="p:*">
  <xsl:element name="{local-name()}">
    <xsl:apply-templates/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

那样结果是

<tem:SendReservation xmlns:tem="http://tempuri.org/">
   <tem:ProviderGuid>1111</tem:ProviderGuid>
   <tem:Username>usertext</tem:Username>
   <tem:Password>passtext</tem:Password>
   <tem:Data><![CDATA[<DATA>
   <ReservationRequest>

      <Reservation>
         <tktReservationGUID>13579</tktReservationGUID>
         <tktState>CA</tktState>
         <LocationId>1357</LocationId>
      </Reservation>
   </ReservationRequest>
</DATA>]]></tem:Data>
</tem:SendReservation>

如果您需要使用XSLT 1.0,那么这里是一个使用纯XSLT 1.0和exsl:node-set函数实现的序列化器的示例:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:p="http://sample.request.com/"
  xmlns:tem="http://tempuri.org/"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="p tem exsl"
  version="1.0">

<xsl:import href="http://lenzconsulting.com/xml-to-string/xml-to-string.xsl"/>

<xsl:output indent="yes" cdata-section-elements="tem:Data" omit-xml-declaration="yes"/>

<xsl:template match="/">
  <tem:SendReservation xmlns:tem="http://tempuri.org/">
     <!--Optional:-->
     <tem:ProviderGuid xmlns:tem="http://tempuri.org/">1111</tem:ProviderGuid>
     <!--Optional:-->
     <tem:Username xmlns:tem="http://tempuri.org/">usertext</tem:Username>
     <!--Optional:-->
     <tem:Password xmlns:tem="http://tempuri.org/">passtext</tem:Password>
     <!--Optional:-->
     <tem:Data>
       <xsl:variable name="data">
         <DATA>
           <xsl:apply-templates select="p:ReservationRequest"/>
         </DATA>
       </xsl:variable>
       <xsl:apply-templates select="exsl:node-set($data)/*" mode="xml-to-string"/>
     </tem:Data>
   </tem:SendReservation>
</xsl:template>

<xsl:template match="p:*">
  <xsl:element name="{local-name()}">
    <xsl:apply-templates/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

我能够稍微更改输入请求,使其与我的响应非常相似。我在下面发布了我的新请求以及用于转换它的XSLT。

新请求:

<p:ReservationRequest xmlns:p="http://sample.request.com/">
  <p:DATA>
      <!--Exactly 1 occurrence-->
      <p:Reservation>
         <p:tktReservationGUID>13579</p:tktReservationGUID>
         <p:tktState>CA</p:tktState>
         <p:LocationId>1357</p:LocationId>
      </p:Reservation>
  </p:DATA>
</p:ReservationRequest>

新XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tem="http://tempuri.org/" xmlns:p="http://sample.request.com/" exclude-result-prefixes="p tem" version="1.0">
      <xsl:output indent="yes" cdata-section-elements="tem:Data"/>
      <xsl:template match="/">
         <tem:SendReservation>
            <!--Optional:-->
            <tem:ProviderGuid>1111</tem:ProviderGuid>
            <!--Optional:-->
            <tem:Username>usertest</tem:Username>
            <!--Optional:-->
            <tem:Password>passtest</tem:Password>
            <!--Optional:-->
            <tem:Data>
               <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
               <xsl:apply-templates select="/p:ReservationRequest/p:DATA"></xsl:apply-templates>
               <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
            </tem:Data>
         </tem:SendReservation>
      </xsl:template>
      <xsl:template match="*">
         <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*|node()"></xsl:apply-templates>
         </xsl:element>
      </xsl:template>
      <xsl:template match="@*">
         <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."></xsl:value-of>
         </xsl:attribute>
      </xsl:template>
   </xsl:stylesheet>

响应:

<tem:SendReservation xmlns:tem="http://tempuri.org/">
   <tem:ProviderGuid>1111</tem:ProviderGuid>
   <tem:Username>usertest</tem:Username>
   <tem:Password>passtest</tem:Password>
   <tem:Data><![CDATA[<DATA>
      <Reservation>
         <tktReservationGUID>13579</tktReservationGUID>
         <tktState>CA</tktState>
         <LocationId>1357</LocationId>
      </Reservation>
</DATA>]]></tem:Data>
</tem:SendReservation>