Grouping nested elements in xslt 1.0

帅比萌擦擦* 提交于 2019-12-24 17:11:30

问题


I've been looking at examples of Muenchian grouping in XSLT 1.0, specifically this example here. However I'm unable to get it working on a more complex XML structure.

My XML currently looks like this:

<?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>

However I want to group the Rank nodes under the same Ranks parent when they have the same Sport and Event. So I want the result to look like this:

<?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>

I'm just a little lost how to do this as the only other examples are dealing with a much simpler structure and I'm not sure if it's possible or how my key and templates need to be structured to do this. Can anyone provide some examples how this might be achieved?

Any advice would be appreciated.


回答1:


This transformation:

<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>

when applied on the provided XML document:

<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>

produces the wanted, correct result:

<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>

Explanation:

Proper use of the Muenchian grouping method and overriding the identity rule.



来源:https://stackoverflow.com/questions/11775595/grouping-nested-elements-in-xslt-1-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!