还有一个关于使用 XSLT 1.0 获得不同值的问题。这是一个愚蠢的虚构示例,应该可以说明我的问题。
<?xml version="1.0" encoding="UTF-8"?>
<moviesByYear>
<year1994>
<movie>
<genre>Action</genre>
<director>A</director>
</movie>
</year1994>
<year1994>
<movie>
<genre>Comedy</genre>
<director>A</director>
</movie>
</year1994>
<year1994>
<movie>
<genre>Drama</genre>
<director>B</director>
</movie>
</year1994>
<year1994>
<movie>
<genre>Thriller</genre>
<director>C</director>
</movie>
</year1994>
<year1995>
<movie>
<genre>Action</genre>
<director>A</director>
</movie>
</year1995>
<year1995>
<movie>
<genre>Comedy</genre>
<director>C</director>
</movie>
</year1995>
<year1996>
<movie>
<genre>Thriller</genre>
<director>A</director>
</movie>
</year1996>
</moviesByYear>
现在假设我想列出所有制作喜剧或导演 B 的电影的年份。我使用以下样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="text" encoding="UTF-8" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="/moviesByYear/*[movie/genre='Comedy' or movie/director='B']">
<xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这给了我以下输出:
year1994year1994year1995
我还没有找到任何解决方案来获得可以在这里工作的不同值。例如,使用完全排除的name(.) != name(following-sibling::*)
原因。year1994
在我的实际案例中,我有一个复杂的 XML 结构和一个带有许多标准的 XPath,这些标准可以挑选出许多节点,我需要从中获得不同节点名称的输出。
更新: michael.hor257k 对此给出了一个优雅的解决方案,但使用它时我遇到了 xsl:key 的问题。请允许我稍微改变一下场景:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<genres>
<genre>Action</genre>
<genre>Comedy</genre>
<genre>Drama</genre>
<genre>Thriller</genre>
</genres>
<moviesByYear>
<year1994>
<movie>
<genre>Action</genre>
<director>A</director>
</movie>
</year1994>
<year1994>
<movie>
<genre>Comedy</genre>
<director>A</director>
</movie>
</year1994>
<year1994>
<movie>
<genre>Drama</genre>
<director>B</director>
</movie>
</year1994>
<year1994>
<movie>
<genre>Thriller</genre>
<director>C</director>
</movie>
</year1994>
<year1995>
<movie>
<genre>Action</genre>
<director>A</director>
</movie>
</year1995>
<year1995>
<movie>
<genre>Comedy</genre>
<director>C</director>
</movie>
</year1995>
<year1996>
<movie>
<genre>Thriller</genre>
<director>A</director>
</movie>
</year1996>
</moviesByYear>
</root>
现在假设我想要一个类型列表,每个类型都列出了制作该类型电影或导演 B 导演的电影的年份。样式表:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="exsl">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="/root/genres/genre">
<xsl:call-template name="output">
<xsl:with-param name="genre">
<xsl:value-of select="."/>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:param name="director" select="'B'"/>
<xsl:key name="year" match="year" use="." />
<xsl:template name="output">
<xsl:param name="genre"/>
<!-- first pass -->
<xsl:variable name="years">
<xsl:for-each select="/root/moviesByYear/*/movie[genre=$genre or director=$director]">
<year><xsl:value-of select="local-name(..)"/></year>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="years-set" select="exsl:node-set($years)" />
<!-- final pass -->
<xsl:value-of select="concat($genre, ': ')"/>
<xsl:for-each select="$years-set/year[count(. | key('year', .)[1]) = 1]">
<xsl:value-of select="."/>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
这会产生以下输出:
Action: year1994year1995
Comedy:
Drama:
Thriller: year1996
如您所见,每年仅列出一次。期望的输出是:
Action: year1994year1995
Comedy: year1994year1995
Drama: year1994
Thriller: year1994year1996