2012-05-16 37 views
0

我有一個相對簡單的Soap響應消息XML,我想用XSLT修改它。如何使用XSLT修改XML Soap響應?

這是我到目前爲止有:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
    xmlns:z="http://some.url/WS/"> 
    <xsl:output method="xml" indent="yes"/> 

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

    <xsl:variable name="Method" select="name(//soap:Body/*)" /> 

    <xsl:template match="//soap:Body/*" > 
     <xsl:choose> 
     <xsl:when test="$Method='Method1Response'"> 
      <xsl:call-template name="Method1" /> 
     </xsl:when> 
     <xsl:otherwise> 

     </xsl:otherwise> 
     </xsl:choose>  
    </xsl:template> 

     <xsl:template name="Method1" match="//soap:Body/z:Method1Response/z:Method1Result/z:Errors" /> 

</xsl:stylesheet> 

示例XML:

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> 
<env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
    <wsa:Action></wsa:Action> 
    <wsa:MessageID></wsa:MessageID> 
    <wsa:RelatesTo></wsa:RelatesTo> 
    <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> 
</env:Header> 
    <soap:Body> 
    <Method1Response xmlns="http://some.url/WS/"> 
     <Method1Result> 
     <Msg>blah blah</Msg> 
     <Errors> 
      <ErrorItem>error 1</ErrorItem> 
      <ErrorItem>error 2</ErrorItem> 
     </Errors> 
     <Data /> 
     </Method1Result> 
    </Method1Response> 
    </soap:Body> 
</soap:Envelope> 

的想法是從Method1Result下,刪除錯誤,如果方法1 =特定值。如果不是,請保持原樣。我現在有什麼,它不是這樣做的。謝謝。

另一個編輯,以進一步闡明: 我想有一個XSLT文件用於多個XML文件,屬於不同的Web服務調用。這意味着Method1可以有多個不同的值,例如:GetMeal,GetWindow,GetHandle,GetWeatherReport,...我希望爲同一個XSLT中的每個值創建一個「case」,以便有意地「打破」預期的XML用於測試目的。每次我將刪除一個不同的元素。

+0

請編輯問題並指定轉換的確切結果。 –

+0

你讓我們猜測哪些是「應該刪除的Method1Result下的幾個元素」,什麼是「如果Method1 =特定值」中的「特定值」 –

回答

0

問題是模板匹配//soap:Body/*調用一個本身不輸出任何內容的命名模板。這導致在soap:Body被忽略的所有elemenets。

由於您已經有了一個模板來匹配要刪除的元素,因此您可以刪除與肥皂相匹配的模板:Body,您應該發現它將按預期工作。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
    xmlns:z="http://some.url/WS/"> 
    <xsl:output method="xml" indent="yes"/> 

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

    <xsl:template match="//soap:Body/z:Method1Response/z:Method1Result/z:Errors" /> 
</xsl:stylesheet> 

當這個應用示例XML,下面是輸出

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> 
    <env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
     <wsa:Action/> 
     <wsa:MessageID/> 
     <wsa:RelatesTo/> 
     <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> 
    </env:Header> 
    <soap:Body> 
     <Method1Response xmlns="http://some.url/WS/"> 
     <Method1Result> 
      <Msg>blah blah</Msg> 
      <Data/> 
     </Method1Result> 
     </Method1Response> 
    </soap:Body> 
</soap:Envelope> 

編輯:沒有理由爲什麼你不能有進一步的匹配模板來處理你可能會回到其他方法響應。例如....

<xsl:template match="//soap:Body/z:GetMealResponse/z:GetMealResult/z:Leftovers" /> 
<xsl:template match="//soap:Body/z:Method1Response/z:Method1Result/z:Errors" /> 
+0

這不是我想到的,因爲它只能解決一半我的問題。我已經有了你描述的解決方案,我想擴展它來涉及$ Method變量。我希望能夠根據該變量的值顯示/隱藏錯誤。因此,xsl:choose標籤等我顯然不太明白這是如何工作的:) – KoturB

+0

沒有理由不能在XSLT中使用多個模板,每個模板都會針對您的每個預期情況。也許用不同的案例添加第二個示例XML有助於更好地解釋事情?謝謝! –

+0

最後這個例子實際上解決了這個問題,謝謝:)我簡直不敢相信它簡單! – KoturB

0

從你的樣式表樣本:

<xsl:variable name="Method" select="name(//soap:Body/*)" /> 

<xsl:template match="//soap:Body/*" > 
    <xsl:choose> 
    <xsl:when test="$Method='Method1Response'"> 
     <xsl:call-template name="Method1" /> 

擺脫變量$Method的,你不需要它。

匹配模式(如match="//soap:Body/*",這是尷尬的),而相比之下,*搜索表達式(如select="name(//soap:Body/*)")通常可以非常簡單,不需要搜索最全的文檔操作(所以你會簡化到match="soap:Body/*")。

而不是使用明確的條件邏輯的,只是提供一個模板,將符合你的特殊情況,並確保它具有比其他候選模板更高的優先級,因此將匹配:

<xsl:template match="z:Method1Response"/><!-- suppressed --> 

或者具有明確提出優先:

<xsl:template match="z:Method1Response" priority="2"/> 

或者更具體地說爲包含錯誤:

<xsl:template match="z:Method1Response[z:Method1Result/z:Errors]"/>