我有一个以下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).
提前致谢,
狮子座
不,模式(在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>
 </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>
 </xsl:text>
<xsl:value-of select="concat('"', @title, '"')"/>
</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)获得.