2

I am trying to save values from an XML doc into a variable. I am aware you can do the following:

<xsl:variable name="variableName" select="xml/node/*"/>

Below is my XML code:

<xml>
<graph2>
    <averageHighTemperatures>
        <January>8.3</January>
        <February>8.5</February>
        <March>11.1</March>
        <April>13.5</April>
        <May>17.1</May>
        <June>20.0</June>
        <July>22.6</July>
        <August>22.5</August>
        <September>19.3</September>
        <October>15.3</October>
        <November>11.2</November>
        <December>9.1</December>
    </averageHighTemperatures>
</graph2>
</xml>

How can I select the value of each month by specifying the node in the XML doc?

Below is my XSL:

    <xsl:variable name="var" select="xml/graph2/averageHighTemperatures/*"/>

    <table>
        <xsl:for-each select="xml/graph2/averageHighTemperatures">
        <tr>
            <td><xsl:value-of select="January $var"/></td>
            <td><xsl:value-of select="February $var"/></td>
        </tr>
        </xsl:for-each>
    </table>

In the above, "January" and "February" are only being used to present the value wanted.

2
  • What is the result you expect to get? Commented Jan 25, 2019 at 23:35
  • So, you are just trying to figure out how to select the specific month from your $var? In the example, you are just trying to indicate that you would only want January and February's temps: <td>8.3</td><td>8.5<td> ? If so, it would be helpful to add an example of the desired output. Your example XSLT is a little confusing, since it isn't clear whether you want "January" and "February" to appear in the output, or if you are just indicating that is the month's value that you want to be able to select. Commented Jan 26, 2019 at 16:36

1 Answer 1

1

Since the month names are the element names, you could select them with a predicate filter matching the local-name():

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:variable name="var" select="xml/graph2/averageHighTemperatures/*"/>

    <table>
        <xsl:for-each select="xml/graph2/averageHighTemperatures">
            <tr>
                <td><xsl:value-of select="'January ', $var[local-name()='January']"/></td>
                <td><xsl:value-of select="'February ', $var[local-name()='February']"/></td>
            </tr>
        </xsl:for-each>
    </table>
  </xsl:template>

</xsl:transform>

If you are going to perform multiple lookups, then a better/faster way to select by name would be to use xsl:key and the key() function:

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="var" match="xml/graph2/averageHighTemperatures/*" use="local-name()"/>

  <xsl:template match="/">
    <table>
        <xsl:for-each select="xml/graph2/averageHighTemperatures">
            <tr>
                <td><xsl:value-of select="'January ', key('var', 'January')"/></td>
                <td><xsl:value-of select="'February ', key('var', 'February')"/></td>
            </tr>
        </xsl:for-each>
    </table>
  </xsl:template>

</xsl:transform>
Sign up to request clarification or add additional context in comments.

6 Comments

That works perfectly thank you. I do have a question regarding the points in the polyline. The line at the moment looks like a crater with a rather than a mountain. I am aware this is because the Y value is plotted 100 (height) - XML value (8) = 92 which is a greater value than say, 100 - XML value (22) = 78. How can I perform an inversion to have the value of 22 plotted above the lesser XML values?
The easiest way to invert the numbers is to multiply by -1, or even just add a "-" when generating the output, but it's difficult to advise without more context. Maybe ask in a separate question with more details describing the issue and examples of desired outcome.
This is weird (for lack of a better word): why are you doing xsl:for-each on a single node? And why are you not doing xsl:for-each on the multiple child nodes, instead of repeating the code for every one of them?
That was in the OP original code sample. Just showing how to answer the question without rewriting the whole thing. Not sure if it was being used to set the context node (for shorter XPaths to keep things DRY), if the real data would have multiple averageHighTemperatures elements, etc. Generally, I would replace an xsl:for-each with xsl:apply-templates.
@MadsHansen Take a look at OP's last three questions.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.