XSLT:在键函数中使用变量

Leo*_*o68 2 xslt

我有一个以下XML文件:

<titles>
   <book title="XML Today" author="David Perry"/>
   <book title="XML and Microsoft" author="David Perry"/>
   <book title="XML Productivity" author="Jim Kim"/>
   <book title="XSLT 1.0" author="Albert Jones"/>
   <book title="XSLT 2.0" author="Albert Jones"/>
   <book title="XSLT Manual" author="Jane Doe"/>
</titles>
Run Code Online (Sandbox Code Playgroud)

我想删除一些元素并应用以下XSLT:

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="author1-search" match="book[starts-with(@author, 'David')]" use="@title"/>
  <xsl:template match="book [key('author1-search', @title)]" />

  <xsl:key name="author2-search" match="book[starts-with(@author, 'Jim')]" use="@title"/>
  <xsl:template match="book [key('author2-search', @title)]" />

  <xsl:template match="/">  
    <xsl:apply-templates />
  </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

是否可以使用内联xsl变量

  <xsl:variable name="Author"> 
    <name>David</name> 
    <name>Jim</name> 
  </xsl:variable> 
Run Code Online (Sandbox Code Playgroud)

而不是"author1-search","author2-search"等,以循环显示名称?

我只能使用XSLT 1.0(目前不支持2.0).

提前致谢,

狮子座

Dim*_*hev 6

不,模式(在XSLT 1.0中)不能包含变量/参数引用.

执行此类任务的一种方法是这样的:

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

 <xsl:param name="pAuthor" select="'David Perry'"/>

    <xsl:key name="kBookaByAuthor" match="book"
             use="@author"/>

    <xsl:template match="/">

     Books written by <xsl:value-of select="$pAuthor"/> :<xsl:text/>
        <xsl:apply-templates
             select="key('kBookaByAuthor', $pAuthor)"/>
    </xsl:template>

    <xsl:template match="book">
     <!-- One can do more formatting here -->
     <xsl:text>&#xA;     </xsl:text>
     <xsl:value-of select="@title"/>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

在提供的XML文档上应用此转换时:

<titles>
    <book title="XML Today" author="David Perry"/>
    <book title="XML and Microsoft" author="David Perry"/>
    <book title="XML Productivity" author="Jim Kim"/>
    <book title="XSLT 1.0" author="Albert Jones"/>
    <book title="XSLT 2.0" author="Albert Jones"/>
    <book title="XSLT Manual" author="Jane Doe"/>
</titles>
Run Code Online (Sandbox Code Playgroud)

产生了想要的正确结果:

Books written by David Perry :
  XML Today
  XML and Microsoft
Run Code Online (Sandbox Code Playgroud)

更新:OP在评论中澄清说:

" 我认为我在最初的问题中完全明确了我的要求.正如我在我的问题和第一次评论中提到的那样,看到处理多个作者的方法对我有帮助 "

这是一个真正使用密钥的解决方案(注意@ Flynn1179的答案中的"密钥"不构建任何索引,只是一个常量的字符串序列 - 所以key()使用它的函数xsl:key实际上是在列表中查找字符串字符串 - 与O(N)形成对比,典型地,O(1)用于在真实索引中搜索):

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

     <xsl:output method="text"/>

     <xsl:param name="pAuthors">
      <x>David Perry</x>
      <x>Jane Doe</x>
     </xsl:param>

     <xsl:variable name="vParams" select=
      "ext:node-set($pAuthors)/*"/>

     <xsl:key name="kBookByAuthor" match="book"
                     use="@author"/>

     <xsl:template match="/">
       Books written by : <xsl:text/>

       <xsl:apply-templates select="$vParams"/>

       <xsl:apply-templates select=
        "key('kBookByAuthor', $vParams)"/>
     </xsl:template>

     <xsl:template match="book">
       <!-- One can do more formatting here -->
       <xsl:text>&#xA;     </xsl:text>
       <xsl:value-of select="concat('&quot;', @title, '&quot;')"/>
     </xsl:template>

     <xsl:template match="x">
      <xsl:if test="not(position() = 1)">, </xsl:if>
      <xsl:value-of select="."/>
     </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

将此转换应用于提供的XML文档(上面)时,会生成所需的正确结果:

   Books written by : David Perry, Jane Doe
     "XML Today"
     "XML and Microsoft"
     "XSLT Manual"
Run Code Online (Sandbox Code Playgroud)

请注意:在此解决方案中使用Exslt函数node-set().这只是为了方便起见.在实际使用中,参数的值将在外部指定,然后该ext:node-set()函数不是必需的.

效率:此解决方案使用XSLT中密钥的真正功能.使用MSXML(3,4和6)XSLT处理器进行的实验表明,如果我们搜索10000个作者,则使用不同XSLT处理器的转换时间范围为:32ms到45ms.

有趣的是,@ Flynn1179提供的解决方案确实没有成为关键索引,并且对于许多XSLT处理器(从相同数量(10000)的作者)到1044ms到5564ms:

MSXML3:5564毫秒,

MSXML4:2526ms,

MSXML6:4867毫秒,

AltovaXML:1044ms.

这是非常低劣的性能与一个真正的关键索引(为32ms到45ms)获得.