XSLT:在关键函数中使用变量 [英] XSLT: Using variables in a key function

查看:26
本文介绍了XSLT:在关键函数中使用变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 XML 文件:

<book title="今日 XML" 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>

我想删除一些元素并应用以下 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:模板></xsl:stylesheet>

是否可以使用内联 xsl 变量

 <姓名>大卫</姓名><姓名>吉姆</姓名></xsl:变量>

而不是author1-search"、author2-search"等来循环名称?

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

提前致谢,

狮子座

解决方案

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

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

<xsl:output method="text"/><xsl:param name="pAuthor" select="'David Perry'"/><xsl:key name="kBookaByAuthor" match="book"使用="@作者"/><xsl:template match="/"><xsl:value-of select="$pAuthor"/> 所著书籍:<xsl:text/><xsl:应用模板select="key('kBookaByAuthor', $pAuthor)"/></xsl:模板><xsl:template match="book"><!-- 可以在这里进行更多格式化--><xsl:text>&#xA;</xsl:text><xsl:value-of select="@title"/></xsl:模板></xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<book title="今日 XML" 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>

产生想要的、正确的结果:

David Perry 所著书籍:今天的 XMLXML 和微软

更新:OP 在评论中澄清:

<块引用>

"我以为我在最初的问题中完全说明了我的要求.正如我在我的问题和我的第一条评论中提到的那样,这将是有助于我了解处理多个的方法作者"

这是一个真正使用键的解决方案(注意@Flynn1179的答案中的键"没有建立任何索引,只是一个常量序列字符串——所以使用 xsl:key 的函数 key() 实际上是在字符串列表中找到一个字符串——这是 O(N) 与,通常,O(1) 用于搜索真正的索引):

<xsl:output method="text"/><xsl:param name="pAuthors"><x>大卫·佩里</x><x>简·多伊</x></xsl:param><xsl:variable name="vParams" select="ext:node-set($pAuthors)/*"/><xsl:key name="kBookByAuthor" match="book"使用="@作者"/><xsl:template match="/">书籍作者:<xsl:text/><xsl:apply-templates select="$vParams"/><xsl:apply-templates select="key('kBookByAuthor', $vParams)"/></xsl:模板><xsl:template match="book"><!-- 可以在这里进行更多格式化--><xsl:text>&#xA;</xsl:text><xsl:value-of select="concat('"', @title, '"')"/></xsl:模板><xsl:template match="x"><xsl:if test="not(position() = 1)">, </xsl:if><xsl:value-of select="."/></xsl:模板></xsl:stylesheet>

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

 书籍作者:David Perry, Jane Doe今天的 XML"XML 和微软"《XSLT 手册》

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

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

有趣的是,@Flynn1179 提出的解决方案确实没有制作关键索引,而且对于许多 XSLT 处理器,它需要(对于相同数量(10000)的作者)从 1044 毫秒到 5564 毫秒::>

MSXML3:5564 毫秒,

MSXML4:2526 毫秒,

MSXML6:4867 毫秒,

AltovaXML:1044 毫秒.

这与使用真正的键索引(32 毫秒到 45 毫秒)获得的性能相当.

I have a following XML file:

<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>

I want to eliminate some elements and apply the following 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>

Is it possible to use an inline xsl variable

  <xsl:variable name="Author"> 
    <name>David</name> 
    <name>Jim</name> 
  </xsl:variable> 

instead of "author1-search", "author2-search", and so on to loop through names?

I can use only XSLT 1.0 (2.0 is currently not supported).

Thanks in advance,

Leo

解决方案

No, patterns (in XSLT 1.0) cannot contain variable/parameter references.

One way to perform such a task would be like this:

<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>

When this transformation is applied on the provided XML document:

<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>

the wanted, correct result is produced:

Books written by David Perry :
  XML Today
  XML and Microsoft

Update: In a comment the OP has clarified that:

"I thought I fully specified my requirements in the initial question. As I mentioned in my question and in my first comment, it would be helpful to me to see the approach for dealing with more than one author"

Here is a solution that truly uses keys (note that the "key" in the answer by @Flynn1179 doesn't build any index and is just a constant sequence of strings-- so the function key() using that xsl:key is actually finding a string in a list of strings -- which is O(N) as contrasted to, typically, O(1) for searching in a true index):

<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>

When this transformation is applied to the provided XML document (above), the wanted, correct result is produced:

   Books written by : David Perry, Jane Doe
     "XML Today"
     "XML and Microsoft"
     "XSLT Manual"

Do note: In this solution the Exslt function node-set() is used. This is done only for convenience here. In a real usage, the value of the parameter will be specified externally and then the ext:node-set() function isn't necessary.

Efficiency: This solution uses the true power of keys in XSLT. An experiment made using MSXML (3, 4 and 6) XSLT processors shows that if we search for 10000 authors the transformation time with different XSLT processors ranges from: 32ms to 45ms.

Interestingly, the solution presented by @Flynn1179 doesn't indeed make key index and with many XSLT processors it takes (for the same number (10000) of authors) from 1044ms to 5564ms:

MSXML3: 5564 ms.,

MSXML4: 2526ms,

MSXML6: 4867 ms,

AltovaXML: 1044ms.

This is quite inferior to the performance one gets with true key indexing (32ms to 45ms).

这篇关于XSLT:在关键函数中使用变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆