Группировка вложенных элементов в xslt 1.0
Я смотрел на примеры мюнхенской группировки в XSLT 1.0, в частности, этот пример здесь. Однако я не могу заставить его работать над более сложной структурой XML.
Мой XML в настоящее время выглядит так:
<?xml version="1.0" encoding="utf-8"?>
<ContestResults>
<Contests>
<Contest sportId="35">
<Sport>Beach Volleyball</Sport>
<Event>Men's</Event>
<Ranks>
<Rank position="1" eventId="1">
<Athlete>Athlete 1a / Athlete 2a [GER]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="1">
<Athlete>Athlete 1b / Athlete 2b [NED]</Athlete>
<Result>0</Result>
</Rank>
</Ranks>
</Contest>
<Contest sportId="32">
<Sport>Tennis</Sport>
<Event>Women's Singles</Event>
<Ranks>
<Rank position="1" eventId="2">
<Athlete>Tennis Athlete 1</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="2">
<Athlete>Tennis Athlete 2</Athlete>
<Result>1</Result>
</Rank>
</Ranks>
</Contest>
<Contest sportId="35">
<Sport>Beach Volleyball</Sport>
<Event>Men's</Event>
<Ranks>
<Rank position="1" eventId="3">
<Athlete>Athlete 3a / Athlete 4a [AUT]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="3">
<Athlete>Athlete 3b / Athlete 4b [SUI]</Athlete>
<Result>0</Result>
</Rank>
</Ranks>
</Contest>
</Contests>
</ContestResults>
Однако я хочу сгруппировать узлы ранга под одним и тем же родителем рангов, когда они имеют одинаковые виды спорта и события. Поэтому я хочу, чтобы результат выглядел так:
<?xml version="1.0" encoding="utf-8"?>
<ContestResults>
<Contests>
<Contest sportId="35">
<Sport>Beach Volleyball</Sport>
<Event>Men's</Event>
<Ranks>
<Rank position="1" eventId="1">
<Athlete>Athlete 1a / Athlete 2a [GER]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="1">
<Athlete>Athlete 1b / Athlete 2b [NED]</Athlete>
<Result>0</Result>
</Rank>
<Rank position="1" eventId="3">
<Athlete>Athlete 3a / Athlete 4a [AUT]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="3">
<Athlete>Athlete 3b / Athlete 4b [SUI]</Athlete>
<Result>0</Result>
</Rank>
</Ranks>
</Contest>
<Contest sportId="32">
<Sport>Tennis</Sport>
<Event>Women's Singles</Event>
<Ranks>
<Rank position="1" eventId="2">
<Athlete>Tennis Athlete 1</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="2">
<Athlete>Tennis Athlete 2</Athlete>
<Result>1</Result>
</Rank>
</Ranks>
</Contest>
</Contests>
</ContestResults>
Я просто немного растерялся, как это сделать, так как единственные другие примеры имеют дело с гораздо более простой структурой, и я не уверен, возможно ли это или как мой ключ и шаблоны должны быть структурированы для этого. Кто-нибудь может привести несколько примеров, как этого можно достичь?
Любой совет будет принят во внимание.
1 ответ
Это преобразование:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kContestById" match="Contest" use="@sportId"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Contests">
<Contests>
<xsl:apply-templates/>
</Contests>
</xsl:template>
<xsl:template match=
"Contest
[not(generate-id()
=
generate-id(key('kContestById', @sportId)[1]))
]"/>
<xsl:template match="Ranks">
<Ranks>
<xsl:apply-templates select="key('kContestById', ../@sportId)/Ranks/Rank"/>
</Ranks>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML:
<ContestResults>
<Contests>
<Contest sportId="35">
<Sport>Beach Volleyball</Sport>
<Event>Men's</Event>
<Ranks>
<Rank position="1" eventId="1">
<Athlete>Athlete 1a / Athlete 2a [GER]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="1">
<Athlete>Athlete 1b / Athlete 2b [NED]</Athlete>
<Result>0</Result>
</Rank>
</Ranks>
</Contest>
<Contest sportId="32">
<Sport>Tennis</Sport>
<Event>Women's Singles</Event>
<Ranks>
<Rank position="1" eventId="2">
<Athlete>Tennis Athlete 1</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="2">
<Athlete>Tennis Athlete 2</Athlete>
<Result>1</Result>
</Rank>
</Ranks>
</Contest>
<Contest sportId="35">
<Sport>Beach Volleyball</Sport>
<Event>Men's</Event>
<Ranks>
<Rank position="1" eventId="3">
<Athlete>Athlete 3a / Athlete 4a [AUT]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="3">
<Athlete>Athlete 3b / Athlete 4b [SUI]</Athlete>
<Result>0</Result>
</Rank>
</Ranks>
</Contest>
</Contests>
</ContestResults>
дает желаемый, правильный результат:
<ContestResults>
<Contests>
<Contest sportId="35">
<Sport>Beach Volleyball</Sport>
<Event>Men's</Event>
<Ranks>
<Rank position="1" eventId="1">
<Athlete>Athlete 1a / Athlete 2a [GER]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="1">
<Athlete>Athlete 1b / Athlete 2b [NED]</Athlete>
<Result>0</Result>
</Rank>
<Rank position="1" eventId="3">
<Athlete>Athlete 3a / Athlete 4a [AUT]</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="3">
<Athlete>Athlete 3b / Athlete 4b [SUI]</Athlete>
<Result>0</Result>
</Rank>
</Ranks>
</Contest>
<Contest sportId="32">
<Sport>Tennis</Sport>
<Event>Women's Singles</Event>
<Ranks>
<Rank position="1" eventId="2">
<Athlete>Tennis Athlete 1</Athlete>
<Result>2</Result>
</Rank>
<Rank position="2" eventId="2">
<Athlete>Tennis Athlete 2</Athlete>
<Result>1</Result>
</Rank>
</Ranks>
</Contest>
</Contests>
</ContestResults>
Пояснение:
Правильное использование метода группирования по Мюнхену и переопределение правила идентичности.