Xml XSLT:在每个子级中查找重复项
我是XSLT/XML新手 我有一个类似以下内容的XML文件:Xml XSLT:在每个子级中查找重复项,xml,xslt,duplicates,xslt-1.0,Xml,Xslt,Duplicates,Xslt 1.0,我是XSLT/XML新手 我有一个类似以下内容的XML文件: <event> <division name="Div1"> <team name="Team1"> <player firstname="A" lastname="F" /> <player firstname="B" lastname="G" /> <player firstname="C" lastname="H"
<event>
<division name="Div1">
<team name="Team1">
<player firstname="A" lastname="F" />
<player firstname="B" lastname="G" />
<player firstname="C" lastname="H" />
<player firstname="D" lastname="G" />
</team>
<team name="Team2">
<player firstname="A" lastname="F" />
<player firstname="B" lastname="G" />
<player firstname="C" lastname="H" />
<player firstname="D" lastname="I" />
</team>
</division>
</event>
我正在尝试编写一个XSL转换(与xsltproc一起使用),以提供同一团队中姓氏相同的玩家的姓名
在四处搜索后,我得出以下结论:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:key name="lastnames" match="player" use="@lastname" />
<xsl:template match="/">
<xsl:for-each select="event/division/team">
<xsl:variable name="dups" select="player[generate-id() = generate-id(key('lastnames', @lastname)[2])]" />
<xsl:if test="$dups">
Team: <xsl:value-of select="@name" /> (<xsl:value-of select="../@name" />)
Players:
<xsl:for-each select="$dups">
<xsl:value-of select="@lastname" />, <xsl:value-of select="@firstname" />.
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
小组:()
玩家:
, .
主要的问题是它给了我所有球队所有球员的副本,而不仅仅是每个球队
在上面的例子中,它应该只返回一个事件(对于Team1中的玩家D G)
小问题:这只打印第二次出现的副本。最好它应该打印第二,第三,第四。。。事件(可以跳过第一个)。
我知道这是因为键函数后面有“[2]”。我发现的大多数例子都是关于如何删除重复项的,这里我需要相反的方法,所以这是我发现的一个技巧,可以提供(接近)我需要的东西。也许有更好的方法来实现这一点
感谢您的帮助
谢谢,
布鲁诺你走对了路!所需的主要更改是对键的调整,尤其是需要考虑
@lastname
值和有关父
元素的唯一信息:
<xsl:key
name="kPlayerByLastnameAndTeam"
match="player"
use="concat(parent::team/@name, '+', @lastname)" />
要看到所有这些都在起作用,请看一下这个完整的解决方案
当此XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key
name="kPlayerByLastnameAndTeam"
match="player"
use="concat(../@name, '+', @lastname)"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="team">
<xsl:apply-templates
select="*[
generate-id() =
generate-id(key(
'kPlayerByLastnameAndTeam',
concat(../@name, '+', @lastname))[1])
]"/>
</xsl:template>
<xsl:template match="player">
<xsl:variable
name="vDups"
select="key(
'kPlayerByLastnameAndTeam',
concat(../@name, '+', @lastname))
[not(generate-id() = generate-id(current()))]"/>
<xsl:if test="$vDups">
<xsl:value-of
select="concat('Team: ', ../@name, ' (', ../../@name, ')')"/>
<xsl:text> Players: </xsl:text>
<xsl:apply-templates select="$vDups" mode="copy"/>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="player" mode="copy">
<xsl:if test="position() > 1">; </xsl:if>
<xsl:value-of select="concat(@lastname, ', ', @firstname, '.')"/>
</xsl:template>
</xsl:stylesheet>
<event>
<division name="Div1">
<team name="Team1">
<player firstname="A" lastname="F"/>
<player firstname="B" lastname="G"/>
<player firstname="C" lastname="H"/>
<player firstname="D" lastname="G"/>
</team>
<team name="Team2">
<player firstname="A" lastname="F"/>
<player firstname="B" lastname="G"/>
<player firstname="C" lastname="H"/>
<player firstname="D" lastname="I"/>
</team>
</division>
</event>
Team: Team1 (Div1)
Players: G, D.
您还可以通过以下方式实现此目的:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:key name="lastnames" match="player" use="@lastname"/>
<xsl:template match="event">
<xsl:text>Team: </xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="team">
<xsl:text> </xsl:text>
<xsl:value-of select="concat(@name,' (',parent::division/@name,')')"/>
<xsl:text> Players: </xsl:text>
<xsl:for-each select="player[@lastname = preceding-sibling::player/@lastname]">
<xsl:value-of select="concat(@lastname,', ', @firstname,'.')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
谢谢你们两位的建议。它现在工作正常:-)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:key name="lastnames" match="player" use="@lastname"/>
<xsl:template match="event">
<xsl:text>Team: </xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="team">
<xsl:text> </xsl:text>
<xsl:value-of select="concat(@name,' (',parent::division/@name,')')"/>
<xsl:text> Players: </xsl:text>
<xsl:for-each select="player[@lastname = preceding-sibling::player/@lastname]">
<xsl:value-of select="concat(@lastname,', ', @firstname,'.')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Team:
Team1 (Div1) Players: G, D.
Team2 (Div1) Players: