开发者

Selecting the unique values from multiple attributes in an XML document using XSLT 1.0

开发者 https://www.devze.com 2023-02-08 13:16 出处:网络
I have the following XML: <League> <Week Date=\"26/04/2010 19:00\"> <Fixture Id=\"542\" HomeTeamId=\"371\" HomeTeam=\"London Raiders Green\" AwayTeamId=\"13\" AwayTeam=\"Richmond Swing

I have the following XML:

<League>
  <Week Date="26/04/2010 19:00">
    <Fixture Id="542" HomeTeamId="371" HomeTeam="London Raiders Green" AwayTeamId="13" AwayTeam="Richmond Swingers" />
    <Fixture Id="543" HomeTeamId="45" HomeTeam="Spartans" AwayTeamId="15" AwayTeam="Panthers" />
    <Fixture Id="544" HomeTeamId="370" HomeTeam="Fat Cats" AwayTeamId="381" AwayTeam="London Raiders Orange" />
  </Week>
  <Week Date="27/04/2010 19:00">
    <Fixture Id="548" HomeTeamId="3" HomeTeam="The Mob" AwayTeamId="81" AwayTeam="London Raiders Red" />
    <Fixture Id="549" HomeTeamId="373" HomeTeam="Intellect" AwayTeamId="83" AwayTeam="Tornadoes" />
  </Week>
</League>

What I would like to do is get a unique list of all the Team Ids within that XML, but the problem is that team ids can either appear in the HomeTeamId or the AwayTeamId attributes in the 开发者_StackOverflowfixture nodes. So I'm struggling to use the standard grouping methods (Grouping using the Muenchian method or selecting unique nodes by checking the preceding sibling).

I can get a list of all the ids this way:

<xsl:for-each select="//Fixture/@HomeTeamId | //Fixture/@AwayTeamId">
    <xsl:sort select="."/>
    <xsl:value-of select="."/><br/>
</xsl:for-each>

But of course when the teams appear in more than one fixture, their id is output more than once using the for-each above.

My ultimate aim is to output a list of fixtures grouped by each team, but I'm struggling with the XSLT here - it's making my brain hurt... Can anyone point me in the right direction?


It shouldn't be a problem to use Muenchian grouping:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output indent="yes"/>

<xsl:key name="k1" match="Fixture/@HomeTeamId | Fixture/@AwayTeamId" use="."/>

<xsl:template match="/">
  <html>
    <head>
      <body>
        <xsl:for-each select="(//Fixture/@HomeTeamId | //Fixture/@AwayTeamId)[generate-id() = generate-id(key('k1', .)[1])]">
          <xsl:sort select="." data-type="number"/>
          <xsl:value-of select="."/>
          <br/>
        </xsl:for-each>
      </body>
    </head>
  </html>
</xsl:template>

</xsl:stylesheet>

I wouldn't use a for-each but instead do apply-templates but as you already had a for-each in your sample I kept that to show how to use the Muenchian grouping with that.


This transformation produces the unique team ids even if their values belonged to any number of differently named attributes:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kTeamById"
  match="@*[name()=document('')/*/my:teamIdNames/*]" use="."/>

 <my:teamIdNames>
   <name>HomeTeamId</name>
   <name>AwayTeamId</name>
 </my:teamIdNames>

 <xsl:variable name="vAttrNames" select=
  "document('')/*/my:teamIdNames/*"/>

 <xsl:template match="/">
  <xsl:apply-templates select=
   "//Fixture/@*[name()=$vAttrNames]"/>
 </xsl:template>

 <xsl:template match=
 "@*[name()=document('')/*/my:teamIdNames/*]
     [generate-id()
     =
      generate-id(key('kTeamById', .)[1])
     ]
 ">
  <xsl:value-of select="."/><br />
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<League>
    <Week Date="26/04/2010 19:00">
        <Fixture Id="542" HomeTeamId="371"
        HomeTeam="London Raiders Green"
        AwayTeamId="13" AwayTeam="Richmond Swingers"/>
        <Fixture Id="543" HomeTeamId="45"
        HomeTeam="Spartans" AwayTeamId="15"
        AwayTeam="Panthers"/>
        <Fixture Id="544" HomeTeamId="370"
        HomeTeam="Fat Cats" AwayTeamId="381"
        AwayTeam="London Raiders Orange" />
    </Week>
    <Week Date="27/04/2010 19:00">
        <Fixture Id="548" HomeTeamId="3"
        HomeTeam="The Mob" AwayTeamId="81"
        AwayTeam="London Raiders Red"/>
        <Fixture Id="549" HomeTeamId="373"
        HomeTeam="Intellect" AwayTeamId="83"
        AwayTeam="Tornadoes"/>
    </Week>
</League>

the wanted result is produced:

371<br/>13<br/>45<br/>15<br/>370<br/>381<br/>3<br/>81<br/>373<br/>83<br/>

Do note:

This solution doesn't assume that the sources of the ids for the teams come just from the attributes named HomeTeamId and AwayTeamId.

In fact, any variable set of names can be used (and included in a separate document), so this is a very powerful, generic solution.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号