2011-08-17 837 views
0

我正在使用XSLT將一些配置XML轉換爲SOAP請求。但是我很難找到一種不需要完整的XPATH表達式並且仍然生成有效的SOAP XML的方法。使用XSLT生成SOAP XML的問題

以下是配置XML的簡化版本。

<CreateOrder> 
    <client_info> 
     <name>John Doe</name> 
     <address> 
      <street1>1211 Lakeview Dr.</street1> 
      <city>New York</city> 
      <state>NY</state> 
      <country>USA</country> 
      <zip>12345</zip> 
     </address> 
    </client_info> 
    <subscriber_number>AAANNNDDDD</subscriber_number> 
</CreateOrder> 

這裏是我正在使用的簡化XSLT。

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" /> 
    <xsl:template match="/"> 
     <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
      <soapenv:Header/> 
      <soapenv:Body> 
       <DirectoryNumber><xsl:value-of select="CreateOrder/subscriber_number"/></DirectoryNumber> 
       <Locale> 
        <xsl:choose> 
         <xsl:when test="CreateOrder/client_info/address/country = 'USA'"> 
          <xsl:text>English (US)</xsl:text> 
         </xsl:when> 
         <xsl:otherwise> 
          <xsl:text>User Defined 1</xsl:text> 
         </xsl:otherwise> 
        </xsl:choose> 
       </Locale> 
      </soapenv:Body> 
     </soapenv:Envelope> 
    </xsl:template> 
</xsl:stylesheet> 

這將生成以下XML輸出 - 這是我的預期/想要的。 [請注意,我不得不美化打印此 - 我的輸出實際上只是問心無愧不換行/縮進單行]

<?xml version="1.0" encoding="UTF-8"?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <DirectoryNumber> 
      AAANNNDDDD 
     </DirectoryNumber> 
     <Locale> 
      English (US) 
     </Locale> 
    </soapenv:Body> 
</soapenv:Envelope> 

通過玩耍,看來我需要使用<xsl:template match="/">整個輸入相匹配文檔,否則我不會將SOAP XML輸入到輸出中。有沒有其他方法可以從XSLT生成一系列新的XML?

但當<xsl:template match="/">存在時,我不能嵌套其他<xsl:template match=...">元件(例如,以匹配「地址」)等具有使用全XPATH表達式節點(如CreateOrder/client_info/address/country)在試驗中。這可行,但並不特別優雅,並且對於真實世界更長的示例而言有點容易出錯。有沒有更好的方法來做到這一點?

回答

1

模板不嵌套。您可以在模板的相應位置使用<xsl:apply-templates.../>實現您想要的效果。在您的簡單示例中,不必指定路徑,但是在更大,更復雜的樣式表中,您可以有許多可重用的模板。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/"> 
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
     <soapenv:Header/> 
     <soapenv:Body> 
     <DirectoryNumber><xsl:value-of select="CreateOrder/subscriber_number"/></DirectoryNumber> 
     <Locale> 
      <xsl:apply-templates select="CreateOrder/client_info/address/country"/> 
     </Locale> 
     </soapenv:Body> 
    </soapenv:Envelope> 
    </xsl:template> 

    <xsl:template match="country"> 
    <xsl:choose> 
     <xsl:when test=". = 'USA'"> 
     <xsl:text>English (US)</xsl:text> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:text>User Defined 1</xsl:text> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

瞭解XSLT的關鍵是要認識到它不是程序性的......您的樣式表不受控制。相反,XSLT處理器正在檢查每個輸入標記,然後在樣式表中搜索匹配的模板。一旦找到並應用了匹配規則,該標籤的處理就完成了。如果您匹配/,則整個文檔將被該模板使用。調用其他模板的唯一方法是通過<xsl:apply-templates select="some xpath"/>告訴處理器使用「some xpath」選擇的節點重新啓動匹配過程。樣式表中的第一個模板匹配/是非常常見的。

+0

謝謝吉姆。對XSLT來說很新,我擔心我錯過了一些東西,或者有更好的方式去做我正在做的事情。因此,接受一個認真解釋的「這就是你所做的」答案確實有幫助。我將開始使用apply-templates結構來使代碼更清晰/更模塊化。 – Torid