我有一个存储电影及其演员的XML文件。
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="index.xsl"?>
<movies
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="movies.xsd">
<movie movieID="1">
<actors>
<actor actorID="1">
<name link="hello">Bob</name>
</actor>
<actor actorID="2">
<name link="hello">Mike</name>
</actor>
</actors>
</movie>
<movie movieID="2">
<actors>
<actor actorID="1">
<name link="hello">Bob</name>
</actor>
<actor actorID="2">
<name>Daniel</name>
</actor>
</actors>
</movie>
</movies>
从上面的代码中可以看出,我有2个“电影”元素,每个元素包含2个“actor”子元素。 4个“name”子元素中的3个包含属性“link”:Bob,Mike,Bob
我正在使用以下XSLT代码仅显示包含属性“link”的actor的名称:
<xsl:template match="/">
<xsl:text>Actors: </xsl:text>
<xsl:apply-templates select="/movies/movie/actors/actor/name[@link]"/>
</xsl:template>
<xsl:template match="name[@link]">
<xsl:value-of select="." />
<xsl:element name="br" />
</xsl:template>
我得到的输出:
Bob
Mike
Bob
正如您所看到的,名称“Bob”重复两次。我想只显示具有属性“link”
的唯一actor名称我尝试过以下XPath 1.0查询:
<xsl:template match="[not(@name[@link] = preceding::@name)]">
<xsl:template match="not(@name[@link] = preceding::@name)">
<xsl:template match="not(@name[@link] = preceding-sibling::@name)">
所有这些都使页面显示错误。
答案 0 :(得分:2)
在XSLT 1.0中进行分组的有效方法是使用Muenchian分组(为了清楚起见,我添加了div
和br
;随意删除它们:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="kName" match="actor/name[@link]" use="." />
<xsl:template match="/">
<div>
<xsl:text>Actors: </xsl:text>
<br />
<xsl:variable name="actorNames"
select="/movies/movie/actors/actor/name[@link]"/>
<xsl:apply-templates
select="$actorNames[generate-id() =
generate-id(key('kName', .)[1])]" />
</div>
</xsl:template>
<xsl:template match="name">
<xsl:value-of select="." />
<br />
</xsl:template>
</xsl:stylesheet>
在样本输入上运行时,会产生:
<div>
Actors: <br />Bob<br />Mike<br />
</div>
答案 1 :(得分:-1)
在 XSLT1.0 中为小型 XML 源做的另一种方法:
<xsl:template match="/">
<xsl:text>Actors: </xsl:text>
<xsl:for-each select="/movies/movie/actors/actor/name[@link and not(. = preceding::*)]">
<xsl:value-of select="."/>
<br/>
</xsl:for-each>
</xsl:template>
输出:
Actors: Bob<br/>Mike<br/>