Q:

Using iteration in XSLT

I have a  following 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')]]" />

Can anybody advice me how I can use a parameter or variable instead of "filename1" and "filename2" to loop through filemanes?
How can the second template be rewritten (perhaps, with adding a new template?) to use an inline xsl, such as
  <xsl:variable name="FileName">
    <name>filename1</name>
    <name>filename2</name>
  </xsl:variable>

Thanks in advance,
Leo

A:

I. XSLT 1.0 solution (this is easier to do with 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>

when applied on this XML document (when will you, people, learn to provide your source 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>

produces the wanted, correct result:
<t>
   <tt>
      <x>
         <y/>
      </x>
      <v-v>
         <p Source="filename3">
            <u/>
            <v/>
         </p>
      </v-v>
   </tt>
</t>

II. XSLT 2.0 solution:
<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>

when this transformation is applied on the same XML document (as above), the same correct result is produced:
<t>
   <tt>
      <x>
         <y/>
      </x>
      <v-v>
         <p Source="filename3">
            <u/>
            <v/>
         </p>
      </v-v>
   </tt>
</t>

