xsl:value-of used as xsl:element name
Asked Answered
C

3

7

I have an incoming XML file with a list structure:

<list>
  <listItem>
    <name>elementOne</name>
    <value>elementOneValue</name>
  </listItem>
  <listItem>
    <name>elementTwo</name>
    <value>elementTwoValue</name>
  </listItem>
</list>

Which I am trying to convert to this structure:

<elementOne>elementOneValue</elementOne>
<elementTwo>elementTwoValue</elementTwo>

This is easy logic to implement with XSL, but I'm running into complications.

<xsl:for-each select="/list/listItem">
  <xsl:element name="<xsl:value-of select="name"/>">
    <xsl:value-of select="value"/>
  </xsl:element>
</xsl:for-each>

Doesn't work because I assume the sequential double quotes are breaking the <xsl:element> tag

<xsl:for-each select="/list/listItem">
  <<xsl:value-of select="name"/>>
    <xsl:value-of select="value"/>
  </<xsl:value-of select="name"/>>
</xsl:for-each>

Doesn't work because I can't use << or >> and

<xsl:for-each select="/list/listItem">
  &lt;<xsl:value-of select="name"/>&gt;
    <xsl:value-of select="value"/>
  &lt;/<xsl:value-of select="name"/>&gt;
</xsl:for-each>

Doesn't work because I end up with > and < in my code instead of XML parseable < or >. I expected this to be a very easy solution but I can't find any records for it on the internet. What is the simple fix I'm overlooking?

Consummation answered 16/1, 2011 at 22:35 Comment(1)
Good question, +1. See my answer for a complete and short solution, using <xsl:element>. :)Dishwasher
D
14

Here is a complete and short solution, using the <xsl:element> XSLT instruction:

<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:template match="listItem">
   <xsl:element name="{name}">
     <xsl:value-of select="value"/>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document (corrected to be well-formed):

<list>
    <listItem>
        <name>elementOne</name>
        <value>elementOneValue</value>
    </listItem>
    <listItem>
        <name>elementTwo</name>
        <value>elementTwoValue</value>
    </listItem>
</list>

the wanted result is produced:

<elementOne>elementOneValue</elementOne>
<elementTwo>elementTwoValue</elementTwo>

Do note:

  1. The use of the <xsl:element> instruction to create an element with statically unknown name.

  2. The use of AVT (Attribute-Value-Template) to specify the name attribute in a compact and more readable way.

  3. It is possible for an error to be raised if the string values of elementOne and elementTwo do not obey the lexical/syntactic rules for an element name (QName).

Dishwasher answered 16/1, 2011 at 22:56 Comment(0)
V
7

I believe you can use curly braces instead of <xsl:value-of>:

<xsl:element name="{name}">
    <xsl:value-of select="value"/>
</xsl:element>
Visakhapatnam answered 16/1, 2011 at 22:42 Comment(1)
I was looking for something else but this is the answer that I was looking for... Thanks!Sunbow
P
0

Didn't try it but this sould work...

   <xsl:for-each select="/list/listItem">
      <xsl:variable name="elemName" select="name"/>
      <xsl:element name="$elemName">
        <xsl:value-of select="value"/>
      </xsl:element>
    </xsl:for-each>
Pub answered 16/1, 2011 at 22:43 Comment(1)
close but you need to escape the variable <xsl:element name="{$elemName}">Thereabout

© 2022 - 2024 — McMap. All rights reserved.