2012-01-17 74 views
2

使用迭代我有以下XSLT:在XSLT

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

    <xsl:template match="node()[child::node() 
      [contains(@Source, 'filename1') 
      or contains(@Source, 'filename2')]]" /> 

任何人能指點我如何通過filemanes使用,而不是「文件名1」和「文件名2」的參數或變量循環?

如何能在第二個模板被改寫(或許,與添加一個新的模板?)使用內聯XSL,如提前

<xsl:variable name="FileName"> 
    <name>filename1</name> 
    <name>filename2</name> 
    </xsl:variable> 

感謝,

利奧

+0

您沒有示出的XML源,但我想知道你是否真的需要包含()在這裏?我問,因爲使用contains()其中「=」會做是一個常見的錯誤;如果是這樣的話,答案將只是'match =「* [*/@ Source = $ FileName/name]」' – 2012-01-18 09:41:09

回答

0

I. XSLT 1.0解決方案(這對於XSLT 2.0更容易):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<my:fileNames> 
    <f>filename1</f> 
    <f>filename2</f> 
</my:fileNames> 

<xsl:variable name="vFilenames" 
       select="document('')/*/my:fileNames/*"/> 

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

<xsl:template match="node()"> 
    <xsl:variable name="vCur" select="."/> 
    <xsl:variable name="vHit"> 
    <xsl:for-each select="$vFilenames"> 
    <xsl:if test= 
    "$vCur/node()[contains(@Source, current())]">1</xsl:if> 
    </xsl:for-each> 
    </xsl:variable> 
    <xsl:choose> 
    <xsl:when test="not(string-length($vHit))"> 
    <xsl:call-template name="identity"/> 
    </xsl:when> 
    </xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

當這個XML文檔(你什麼時候,人,學習提供源XML ???)施加:

<t> 
    <tt> 
     <x> 
      <y/> 
     </x> 
     <mm> 
      <z Source="filename1"> 
       <u/> 
       <v/> 
      </z> 
     </mm> 
     <rr> 
      <m Source="filename2"> 
       <u/> 
       <v/> 
      </m> 
     </rr> 
     <v-v> 
      <p Source="filename3"> 
       <u/> 
       <v/> 
      </p> 
     </v-v> 
    </tt> 
</t> 

產生想要的,正確的結果

<t> 
    <tt> 
     <x> 
     <y/> 
     </x> 
     <v-v> 
     <p Source="filename3"> 
      <u/> 
      <v/> 
     </p> 
     </v-v> 
    </tt> 
</t> 

二, XSLT 2.0溶液:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:param name="pFileNames"> 
    <f>filename1</f> 
    <f>filename2</f> 
</xsl:param> 

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

<xsl:template match= 
    "node()[node() 
      [some $fn in $pFileNames/f 
      satisfies 
       contains(@Source, $fn) 
      ] 
     ]"/> 
</xsl:stylesheet> 

當這種轉變是在同一個XML文檔應用(如上述)中,相同的正確的結果產生

<t> 
    <tt> 
     <x> 
     <y/> 
     </x> 
     <v-v> 
     <p Source="filename3"> 
      <u/> 
      <v/> 
     </p> 
     </v-v> 
    </tt> 
</t> 
+0

非常感謝您提供有用的建議和寶貴的建議。示例XML文件適合我的需求。目前我必須使用XSLT 1.0;由於這個原因,邁克爾的推薦似乎並不直接適用於我的任務。另一個限制是我不能使用文檔funciton;所以我用我故意在我的模板中使用contains()然而,在其他情況下使用「=」也可能很重要,所以我也會對這種情況的解決方案非常感興趣 – Leo68 2012-01-19 16:43:33

+0

您好Dimitre,當然,我想確認接受這個答案。我必須在本網站的某個地方進行確認嗎?順便說一句,在我之前的評論中,當使用「=」而不是「contains」時,我問你和Michael對模板規範的建議。如果你能勾畫出相應的方法,那對我來說會非常有幫助。感謝和regatrds,獅子座 – Leo68 2012-01-23 11:40:13

+0

@ Leo68:是的,接受答案是通過點擊這個答案旁邊的「複選標記」來完成的。至於'contains()'和'=',前者更鬆散,後者更嚴格。 'contains($ String,$ Pattern)'當'$ String' *包含字符串'$ Pattren'時 - '$ String'中的任何位置時,''計算爲'true()'。 '='另一方面要求'$ String'完全等於(字符串長度和字符)到'$ Pattern'。還有兩個類似'contains()'的函數存在:'starts-with()'和(在XPath 2.0中)'ends-with()'。不確定模式在字符串中的位置時,使用'contains()' – 2012-01-23 12:38:22