0

Given the following xml document...

   <ws>
       <series year="2005" mvp="Jermaine Dye">
          <team name="Chicago White Sox" wins="4" />
          <team name="Houston Astros" wins="0" />
       </series>
       <series year="2004" mvp="Manny Ramirez">
          <team name="Boston Red Sox" wins="4" />
          <team name="St. Louis Cardinals" wins="0" />
       </series>
    </ws>

I have created a key to get the name attribute of the first team in each series, and I am trying to loop through and list out each name for each series as follows; I am currently not returning any results and am not sure what is wrong with my value-of reference?...

<xsl:key name="winners" match="team[1]" use="@name" />

    <xsl:template match="/">
        <xsl:for-each select="ws/series">
             <xsl:value-of select="key('winners', @name)" />
        </xsl:for-each>
    </xsl:template>

Expected output would be...

Chicago White Sox (the first team from series 1)
Boston Red Sox (the first team from series 2)

The xml data I have provided only includes 2 series elements when in actuality there are hundred's. The key is used to speed up the transformation process and works along with other keys to generate my result document.

codingManiac
  • 1,654
  • 4
  • 29
  • 42
  • Why is a key necessary here? Isn't the winner the first child team of the **current** series? P.S. This would be a lot clearer if we could see the required output. – michael.hor257k Feb 20 '14 at 02:25
  • @michael.hor257k I revised my post to hopefully be more helpful. I know that the for-each loop runs fine, it's just not displaying the team names as I want it to. – codingManiac Feb 20 '14 at 02:40

2 Answers2

1

I am trying to list out the name of the first team in each series

Using a key is an unnecessary complication for such a simple task. Try simply:

<xsl:template match="/">
    <xsl:for-each select="ws/series">
        <xsl:value-of select="team[1]/@name" />
    </xsl:for-each>
</xsl:template>

Of course, you will want to add some kind of wrapper or separator to this, otherwise you'll just get a jumble of all names - say (assuming the output method is text):

<xsl:template match="/">
    <xsl:for-each select="ws/series">
        <xsl:value-of select="team[1]/@name" />
        <xsl:if test="position()!=last()">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

EDIT:

To do this (artificially) using a key, you must ask yourself what is connecting a team to its series (other than being a child thereof). The answer here is 'nothing'. However, a team has access to its parent series data. Therefore we could identify a team by some attribute of its parent series, such as the year or the MVP. The MVP might not be unique to the series, so let's make the key:

<xsl:key name="team-by-year" match="team" use="parent::series/@year" />

This says: if you tell me the year, I'll tell you the teams that played in the series of that year. So from here, it's simply a matter of calling a key with the current series' year:

<xsl:template match="/">
    <xsl:for-each select="ws/series">
        <xsl:value-of select="key('team-by-year', @year)[1]/@name" />
        <xsl:if test="position()!=last()">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • I don't have a choice in using the key :( is there anyway to reference the name attribute with the key instead? EDIT: I believe the use of key is as unnecessary just as you believe it is, however, I am trying to learn to use keys to reference node sets. – codingManiac Feb 20 '14 at 02:41
  • "*I don't have a choice in using the key*" Why? – michael.hor257k Feb 20 '14 at 02:44
  • It is part of an xsl exercise I am working on and I am trying to get a basic grasp of how to reference the data I need using a given key. – codingManiac Feb 20 '14 at 02:46
  • Not assigned, I am simply going through a book on XML and am doing every single exercise to try and improve my understanding of the content. XSL has proven much more tricky to me than say PHP or Java procedural or object oriented approaches to coding. – codingManiac Feb 20 '14 at 02:54
  • Well, this is not a good exercise, because the correct answer here is: no key is necessary. Basically, you are asking how to send a telegram to someone standing right next to you. Anyway, I have edited my answer to include this "method". – michael.hor257k Feb 20 '14 at 03:17
  • Thank you, I agree with you, as I feel the same about many other textbooks I have referenced exercises from. Despite the fact that I may know how to perform something one way being forced to do it another just to push a concept is absurd. – codingManiac Feb 20 '14 at 03:22
0

If you use this

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

    <xsl:key name="winners" match="team[1]" use="@name" />

    <xsl:template match="/">
        <xsl:for-each select="ws/series/*">
            <xsl:value-of select="key('winners', @name)/@name" />
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>
Joel M. Lamsen
  • 7,143
  • 1
  • 12
  • 14