user1818397
user1818397

Reputation: 79

Trying to read xml element value in xsl

I am new to XSL. I am trying to read values of XML elements using a XSL file. My XML file is like:

<PersonList>
  <Person>
    <Name>person1</Name>
    <Age>21</Age>
  </Person>
  <Person>
    <Name>person2</Name>
    <Age>21</Age>
  </Person>
</PersonList>

My XSL file is like:

<xsl:stylesheet version="1.0" xmlns=...>
  <xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml declaration="no" />
  <xsl template match="/">
    <PersonList>
      <xsl:for-each select="PersonList/Person">
        <Person>
          <xsl:for-each select="*">
            <xsl:variable name="elementName">
              <xsl:value-of select="name(.)" />
            </xsl:variable>
            <xsl:variable name="elementValue">
              ???
            </xsl:variable>
          </xsl:for-each>
        </Person>
      </xsl:for-each>
    </PersonList> 
  </xsl:template>
</xsl:stylesheet>

How should I replace ??? to get the value of the element stored in the elementName variable. I tried the following three lines separately:

<xsl:value-of select="value(.)" /> 
<xsl:value-of select="value($elementName)" />
<xsl:value-of select="$elementName" />

but no luck. Please help!

Upvotes: 2

Views: 32355

Answers (2)

Francis Avila
Francis Avila

Reputation: 31641

Your ?????????????????? can be <xsl:value-of select="."/> (i.e. the string-value of the context element.) It has no connection to $elementName.

You can do this much more succinctly like this:

<xsl:for-each select="*">
  <xsl:variable name="elementName" select="name()"/>
  <xsl:variable name="elementValue" select="string(.)"/>
</xsl:for-each>

However your template is really strange. You're collecting these variables but you're not doing anything with them--they won't appear in the output. What output are you trying to get?

Use of for-each is generally a code smell. In almost all cases you're better off with multiple templates:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="no" />

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Person/*">
    <xsl:variable name="elementName" select="name()"/>
    <xsl:variable name="elementValue" select="string(.)"/>
</xsl:template>

</xsl:stylesheet>

This pattern where you copy almost everything and change just a little bit of the xml is very common and very powerful and you should learn how to use it.

Upvotes: 3

Tim C
Tim C

Reputation: 70648

Well, if you really wanted to get the value of an element whose name is held in a variable, in your case you would do it like this

<xsl:variable name="elementValue">
    <xsl:value-of select="../*[name()=$elementName]" />
</xsl:variable>

But, this is greatly overcomplicated matters. You are in a xsl:for-each loop, iterating over the child elements of a Person. Therefore, because you are already positioned on the element for which you want the value, you can just do this and forget about the elementName variable.

<xsl:variable name="elementValue">
    <xsl:value-of select="."/>
</xsl:variable>

In fact, in you could simplify your loops to just this

<xsl:for-each select="PersonList/Person">
   <Person>
      <xsl:for-each select="*">
         <xsl:value-of select="." />
      </xsl:for-each>
   </Person>
</xsl:for-each>

Upvotes: 0

Related Questions