2010-03-24 50 views
2

我試圖保留我的xsl DRY,並且因此我想調用同一個模板來處理碰巧是相同的複雜類型(ContactDetails和AltContactDetails)。鑑於以下XML:爲同一複雜類型的不同節點名稱調用相同的xsl:模板

<?xml version="1.0" encoding="UTF-8"?> 
<RootNode> 
    <Name>Bob</Name> 
    <ContactDetails> 
     <Address> 
      <Line1>1 High Street</Line1> 
      <Town>TownName</Town> 
      <Postcode>AB1 1CD</Postcode> 
     </Address> 
     <Email>[email protected]</Email> 
    </ContactDetails> 
    <AltContactDetails> 
     <Address> 
      <Line1>3 Market Square</Line1> 
      <Town>TownName</Town> 
      <Postcode>EF2 2GH</Postcode> 
     </Address> 
     <Email>[email protected]</Email> 
    </AltContactDetails> 
</RootNode> 

我寫了一個XSL樣式表如下:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="/"> 
     <PersonsName> 
      <xsl:value-of select="RootNode/Name"/> 
     </PersonsName> 
     <xsl:call-template name="ContactDetails"> 
      <xsl:with-param name="data"><xsl:value-of select="RootNode/ContactDetails"/></xsl:with-param> 
      <xsl:with-param name="elementName"><xsl:value-of select="'FirstAddress'"/></xsl:with-param> 
     </xsl:call-template> 
     <xsl:call-template name="ContactDetails"> 
      <xsl:with-param name="data"><xsl:value-of select="RootNode/AltContactDetails"/></xsl:with-param> 
      <xsl:with-param name="elementName"><xsl:value-of select="'SecondAddress'"/></xsl:with-param> 
     </xsl:call-template> 
    </xsl:template> 
    <xsl:template name="ContactDetails"> 
     <xsl:param name="data"></xsl:param> 
     <xsl:param name="elementName"></xsl:param> 
     <xsl:element name="{$elementName}"> 
      <FirstLine> 
       <xsl:value-of select="$data/Address/Line1"/> 
      </FirstLine> 

      <Town> 
       <xsl:value-of select="$data/Address/Town"/> 
      </Town> 
      <PostalCode> 
       <xsl:value-of select="$data/Address/Postcode"/> 
      </PostalCode> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

當我嘗試運行樣式表它的抱怨,我認爲我需要:

要在路徑表達式使用結果樹片段,或者使用exsl:節點集()或指定版本1.1

我不想去1.1版本。所以沒有人知道如何獲得exsl:節點集()對於上面的例子中工作?

或者,如果有人知道一個更好的方式,以相同的模板適用於2個不同的部分,然後也將真正幫助我嗎?

感謝

戴夫

回答

8

你是從錯誤的一端卷這件事(錯誤的一端是幾乎總是:試圖將命令式編程範式應用於XSLT)。

這是很容易通過模板匹配的事情。

<xsl:template match="RootNode"> 
    <PersonsName> 
    <xsl:value-of select="Name"/> 
    </PersonsName> 
    <xsl:apply-templates select="ContactDetails|AltContactDetails" /> 
</xsl:template> 

<xsl:template match="ContactDetails|AltContactDetails"> 
    <xsl:copy> 
    <FirstLine> 
     <xsl:value-of select="Address/Line1"/> 
    </FirstLine> 
    <Town> 
     <xsl:value-of select="Address/Town"/> 
    </Town> 
    <PostalCode> 
     <xsl:value-of select="Address/Postcode"/> 
    </PostalCode> 
    </xsl:copy> 
</xsl:template> 

放手你必須告訴XSLT處理器該怎麼做(通過製作命名模板並調用它們,「命令式」)。

的XSLT處理器選擇什麼模板調用。從根(/)開始,遞歸檢查它所訪問的每個節點的匹配模板。它自己遍歷所有輸入XML - 唯一的工作就是爲它提供匹配的模板,以便用特殊方式處理那些您想要處理的節點。

對於那些需要特殊處理的節點,您可以放入自定義模板,並且在XSLT處理器出現後調用XSLT處理器。所有你需要確保你的模板是遍歷通過聲明適當<xsl:apply-templates />推移。

+0

謝謝你......我不知道在模板匹配管道。這真的幫了我。 – CraftyFella 2010-03-24 17:20:04

+0

@CraftyFella:這些所謂的「匹配表達式」是XPath的一個子集,在XPath中工作的很多事情也可以在這裏工作。 – Tomalak 2010-03-24 17:25:56

+0

很好的答案! +1 – 2010-03-24 18:09:58

2

爲什麼不把模板

<xsl:template match="ContactDetails|AltContactDetails"> 

,並做了測試,以確定該模板,而不是內部的輸出元素的名稱?

+0

Frickin甜..完全工程..我會寫了完整的答案,因爲我不得不將其更改爲XSL:applytemplates而不是電話:模板 – CraftyFella 2010-03-24 17:17:09