2012-12-13 83 views
4

我有下面的XML:XSL:變量的xsl:複製的選擇

<?xml version="1.0" encoding="UTF-8"?> 
<XmlTest> 
    <Pictures attr="Pic1">Picture 1</Pictures> 
    <Pictures attr="Pic2">Picture 2</Pictures> 
    <Pictures attr="Pic3">Picture 3</Pictures> 
</XmlTest> 

雖然這XSL做什麼預期(輸出的第一張照片的ATTR):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/XmlTest"> 
     <xsl:variable name="FirstPicture" select="Pictures[1]"> 
     </xsl:variable> 
     <xsl:value-of select="$FirstPicture/@attr"/> 
    </xsl:template> 
</xsl:stylesheet> 

它似乎是不可能使用XSL做同樣的變量聲明中:複製的:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 
    <xsl:template match="/XmlTest"> 
     <xsl:variable name="FirstPicture"> 
      <xsl:copy-of select="Pictures[1]"/> 
     </xsl:variable> 
     <xsl:value-of select="$FirstPicture/@attr"/> 
    </xsl:template> 
</xsl:stylesheet> 

好奇: 如果我在第二個例子中選擇「$ FirstPicture」而不是「$ FirstPicture/@ attr」,它會按照預期輸出圖片1的文本節點...

在大家建議我重寫代碼之前: 這只是一個簡單的測試,我真正的目標是使用一個命名模板來選擇一個節點放入變量FirstPicture中,並將其用於進一步選擇。

我希望有人能夠幫助我理解行爲,或者可以建議我選擇一個可以輕鬆重複使用的代碼的節點(這個節點是第一個節點在我的實際應用中是複雜的)的正確方法。謝謝。

編輯(感謝馬丁Honnen): 這是我的工作溶液的例子(其中另外使用一個單獨的模板來選擇所請求的圖像節點),使用MS XSLT處理器:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    version="1.0"> 
    <xsl:template match="/XmlTest"> 
     <xsl:variable name="FirstPictureResultTreeFragment"> 
      <xsl:call-template name="SelectFirstPicture"> 
       <xsl:with-param name="Pictures" select="Pictures" /> 
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:variable name="FirstPicture" select="msxsl:node-set($FirstPictureResultTreeFragment)/*"/> 
     <xsl:value-of select="$FirstPicture/@attr"/> 
     <!-- further operations on the $FirstPicture node --> 
    </xsl:template> 

    <xsl:template name="SelectFirstPicture"> 
     <xsl:param name="Pictures"/> 
     <xsl:copy-of select="$Pictures[1]"/> 
    </xsl:template> 
</xsl:stylesheet> 

不很好,它在XSLT 1.0中不可能直接從模板輸出節點,但是使用額外的變量至少不是不可能的。

+2

爲什麼要執行復制子樹的昂貴操作?副本中的屬性與原始副本中的屬性相同。只需使用選擇表格 - 效率更高。並且避免了與結果樹片段相關的XSLT 1.0限制。 –

+0

爲了處理我的例子,你是絕對正確的,選擇完整的節點集將會是開銷。在我的真實應用程序中,我不只是想選擇一個屬性,而是需要對此節點進行進一步的操作,如選擇子節點和調用其他模板。我想在我的xsl的幾個地方使用它,而不需要複製任何代碼。 –

回答

4
與如果這樣做

<xsl:variable name="FirstPicture"> 
     <xsl:copy-of select="Pictures[1]"/> 
    </xsl:variable> 

這個變量是一個結果樹片段和所有可以與在純XSLT 1.0做與copy-of(或value-of)輸出它的XSLT 1.0處理器

井。如果你想申請的XPath,你首先需要將結果樹片段轉換爲節點集,最XSLT 1.0處理器,支持對擴展功能,因此儘量

<xsl:variable name="FirstPictureRtf"> 
     <xsl:copy-of select="Pictures[1]"/> 
    </xsl:variable> 
    <xsl:variable name="FirstPicture" select="exsl:node-set(FirstPictureRtf)/Pictures/@attr"> 

,你在你的樣式表定義xmlns:exsl="http://exslt.org/common"

請注意,您需要檢查您的XSLT 1.0處理器是否支持EXSLT擴展功能或其他名稱空間中的類似擴展功能(例如各種MSXML版本)。

+1

儘管VS Debugger窗口將變量顯示爲類型NodeSet,但您正確的是copy-of返回結果樹片段:-( 我必須引入第二個變量,如您所建議的那樣將其轉換爲節點集。 –