2013-02-13 26 views
4

我正在將簡單的SOAP XML消息轉換爲更加擴展的SOAP XML消息。我幾乎可以工作,但我無法解決最後兩個問題。我的問題是:將元素從源複製到CDATA部分的XSLT

  1. 元素之後的所有元素應該位於CDATA節中。我嘗試使用'cdata-section-elements',但無法使其工作。
  2. 元素應該是這樣的

我的源XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <SOAP-ENV:Header/> 
    <SOAP-ENV:Body> 
    <test> 
     <element1>123</element1> 
     <element2>123</element2> 
    </test> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

我的XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" exclude-result-prefixes="fn xs SOAP-ENV"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" /> 

<!-- Special rule to match the document root only --> 
<xsl:template match="/*"> 
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"> 
     <xsl:namespace name="a" select="'http://www.w3.org/2005/08/addressing'"/> 
     <xsl:apply-templates select="@*|node()"/> 
    </s:Envelope> 
</xsl:template> 

<!-- Expand soap header --> 
<xsl:template match="SOAP-ENV:Header"> 
    <xsl:element name="s:{local-name()}" namespace="http://www.w3.org/2003/05/soap-envelope"> 
     <xsl:element name="a:Action" namespace="http://www.w3.org/2005/08/addressing"> 
      <xsl:attribute name="s:mustUnderstand" namespace="http://www.w3.org/2003/05/soap-envelope">1</xsl:attribute> 
      <xsl:text>http://www.ortec.com/CAIS/IApplicationIntegrationService/SendMessage</xsl:text> 
     </xsl:element> 
    </xsl:element> 
</xsl:template> 

<!-- Change soap body --> 
<xsl:template match="SOAP-ENV:Body"> 
    <xsl:element name="s:{local-name()}" namespace="http://www.w3.org/2003/05/soap-envelope"> 
     <xsl:element name="cais:SendMessage" namespace="http://www.ortec.com/CAIS"> 
      <xsl:element name="cais:message" namespace="http://www.ortec.com/CAIS"> 
       <!-- copy the rest --> 
       <xsl:apply-templates select="child::node()"/> 
      </xsl:element> 
      <xsl:element name="cais:commandName" namespace="http://www.ortec.com/CAIS">Import</xsl:element> 
     </xsl:element> 
    </xsl:element> 
</xsl:template> 

<!-- template for the copy of the rest --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

錯誤輸出我現在有了這個XSLT得到:

<?xml version="1.0" encoding="UTF-8"?> 
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope"> 
    <s:Header> 
    <a:Action s:mustUnderstand="1">http://www.ortec.com/CAIS/IApplicationIntegrationService/SendMessage</a:Action> 
    </s:Header> 
    <s:Body> 
    <cais:SendMessage xmlns:cais="http://www.ortec.com/CAIS"> 
     <cais:message> 
     <test xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
      <element1>123</element1> 
      <element2>123</element2> 
     </test> 
     </cais:message> 
     <cais:commandName>Import</cais:commandName> 
    </cais:SendMessage> 
    </s:Body> 
</s:Envelope> 

我的期望輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope"> 
    <s:Header> 
    <a:Action s:mustUnderstand="1">http://www.ortec.com/CAIS/IApplicationIntegrationService/SendMessage</a:Action> 
    </s:Header> 
    <s:Body> 
    <cais:SendMessage xmlns:cais="http://www.ortec.com/CAIS"> 
     <cais:message> 
     <![CDATA[ 
     <test> 
      <element1>123</element1> 
      <element2>123</element2> 
     </test> 
     ]]> 
     </cais:message> 
     <cais:commandName>Import</cais:commandName> 
    </cais:SendMessage> 
    </s:Body> 
</s:Envelope> 
+0

+1,記錄完備的問題!如果只有所有的XSLT問題都包含輸入XML,嘗試的XSLT,期望的輸出和實際輸出。 – LarsH 2013-04-11 15:50:39

回答

7

可能會在下面的工作?:

<xsl:template match="SOAP-ENV:Body"> 
    <xsl:element name="s:{local-name()}" namespace="http://www.w3.org/2003/05/soap-envelope"> 
     <xsl:element name="cais:SendMessage" namespace="http://www.ortec.com/CAIS"> 
      <xsl:element name="cais:message" namespace="http://www.ortec.com/CAIS"> 
       <!-- copy the rest --> 
       <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
       <xsl:apply-templates select="child::node()"/> 
       <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
      </xsl:element> 
      <xsl:element name="cais:commandName" namespace="http://www.ortec.com/CAIS">Import</xsl:element> 
     </xsl:element> 
    </xsl:element> 
</xsl:template> 

當我修改XSLT以這種方式和你的樣品輸入運行它,我得到:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"> 
    <s:Header><a:Action s:mustUnderstand="1" xmlns:a="http://www.w3.org/2005/08/addressing">http://www.ortec.com/CAIS/IApplicationIntegrationService/SendMessage</a:Action></s:Header> 
    <s:Body><cais:SendMessage xmlns:cais="http://www.ortec.com/CAIS"><cais:message> 
    <![CDATA[ 
    <test xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
     <element1>123</element1> 
     <element2>123</element2> 
    </test> 
    ]]> 
    </cais:message> 
    <cais:commandName>Import</cais:commandName></cais:SendMessage></s:Body> 
</s:Envelope> 

命名空間聲明仍然存在,但這應該不重要。

如果你確實想在<test>擺脫空間聲明中,你可以用這個替換您的身份模板:

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

    <xsl:template match="*"> 
    <xsl:element name="{name()}"> 
     <xsl:apply-templates select="@* | node()" /> 
    </xsl:element> 
    </xsl:template> 

我驗證過,似乎工作。正如旁註所示,如果您提前知道元素的前綴和名稱,則不需要使用xsl:elementnamespace屬性。如果您在xsl:spreadsheet元素來定義你的命名空間:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        xmlns:fn="http://www.w3.org/2005/xpath-functions" 
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:s="http://www.w3.org/2003/05/soap-envelope" 
        xmlns:cais="http://www.ortec.com/CAIS" 
        exclude-result-prefixes="fn xs SOAP-ENV cais"> 

然後,你可以這樣做:

<xsl:template match="SOAP-ENV:Body"> 
    <xsl:element name="s:{local-name()}"> 
     <cais:SendMessage> 
      <cais:message> 
       <!-- copy the rest --> 
       <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
       <xsl:apply-templates select="child::node()"/> 
       <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
      </cais:message> 
      <cais:commandName>Import</cais:commandName> 
     </cais:SendMessage> 
    </xsl:element> 
</xsl:template> 
+0

謝謝你解決了關於CDATA的第一個問題。仍在元素中與命名空間掙扎。 – 2013-02-13 11:04:59

+0

@MarkVeenstra增加了一個建議來擺脫名稱空間聲明。 – JLRishe 2013-02-13 11:07:51

+0

謝謝你的幫助! – 2013-02-13 13:12:57

1

使用copy-namespace="no"xsl:copy-of元素,以避免在test元素名稱空間的邊界:

<xsl:template match="SOAP-ENV:Body"> 
<xsl:element name="s:{local-name()}"> 
    <xsl:element name="cais:SendMessage"> 
    <xsl:element name="cais:message"> 
    <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
    <xsl:copy-of select="test" copy-namespaces="no"/> 
    <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
    </xsl:element> 
    <xsl:element name="cais:commandName"><xsl:text>Import</xsl:text> 
</xsl:element> 
    </xsl:element> 
</xsl:element> 
</xsl:template> 
</xsl:stylesheet>