Hi,
I have an XML:

<A>
  <B>
    <C>a</C>
  </B>
  <B>
     <C>b</C>
  </B>
  <B>
     <C>c</C>
  </B>
</A>

and I need the output as

<X name="a">
  <Y name="b">
    <Z name ="c"/>
  </Y>
</X>

i don't know how to write the XSL for it, tried few things but couldn't get the solution.

Tried XSL-

<xsl:variable name="i">
<xsl:value-of select="A/B/C"/>
</xsl:variable>
<X name={$i}>
  <xsl:variable name="j">
   <xsl:value-of select="A/B/C"/>
  </xsl:variable>
  <Y name={$j}>
      <xsl:variable name="k">
        <xsl:value-of select="A/B/C"/>
      </xsl:variable>
      <Z name={$k}/>
   </Y>
</X>

it gives output as

<X name="a">
  <Y name="a">
    <Z name ="a"/>
  </Y>
</X>

Please advise

Dani AI

Generated

— the reason your three variables all printed the same value is that your approach pulled the first C value from the node-set each time (and you stored strings rather than the specific node you meant to process). 's explicit B[1], B[2], B[3] solution works because it picks each position by index, but a more general way to "go to the next node" without using for-each is to recurse on the following-sibling axis: process the current B, then call the same template on $b/following-sibling::B[1].

The pattern is: pass the current B as a parameter and a level counter; emit the element whose name maps to that level (X, Y, Z, ...); set the element's name attribute from the current B/C child; then recurse on the next sibling until none remains. Key tips: pass nodes via select so you keep node-sets (not string RTFs), and use following-sibling::B[1] to get the immediate next B.

A compact recursive template skeleton (to insert inside a normal XSLT stylesheet) looks like this:

<!-- call from the root: pass the first B and level 1 -->
<xsl:call-template name="nest">
  <xsl:with-param name="b" select="/A/B[1]"/>
  <xsl:with-param name="level" select="1"/>
</xsl:call-template>

<xsl:template name="nest">
  <xsl:param name="b"/>
  <xsl:param name="level"/>
  <xsl:if test="$b">
    <xsl:choose>
      <xsl:when test="$level = 1">
        <X name="{ $b/C }">
          <xsl:call-template name="nest">
            <xsl:with-param name="b" select="$b/following-sibling::B[1]"/>
            <xsl:with-param name="level" select="$level + 1"/>
          </xsl:call-template>
        </X>
      </xsl:when>
      <xsl:when test="$level = 2">
        <Y name="{ $b/C }">
          <xsl:call-template name="nest">
            <xsl:with-param name="b" select="$b/following-sibling::B[1]"/>
            <xsl:with-param name="level" select="$level + 1"/>
          </xsl:call-template>
        </Y>
      </xsl:when>
      <xsl:when test="$level = 3">
        <Z name="{ $b/C }">
          <xsl:call-template name="nest">
            <xsl:with-param name="b" select="$b/following-sibling::B[1]"/>
            <xsl:with-param name="level" select="$level + 1"/>
          </xsl:call-template>
        </Z>
      </xsl:when>
      <!-- add more cases or a generic fallback here -->
    </xsl:choose>
  </xsl:if>
</xsl:template>

Troubleshooting: ensure you pass the node with select (not by embedding value-of), normalize whitespace if C may contain extra text, and extend the level-to-name mapping if you can have more than three B nodes. If XSLT 2.0 is available, sequences and computed element names or a small template that maps position to a name make the implementation cleaner.

Here is a non-recursion based solution:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

  <xsl:output method="xml" />

  <xsl:template match="/">
     <xsl:element name="X">
        <xsl:attribute name="name">
           <xsl:value-of select="//B[1]/C" />
        </xsl:attribute>
        <xsl:element name="Y">
           <xsl:attribute name="name">
              <xsl:value-of select="//B[2]/C" />
           </xsl:attribute>
           <xsl:element name="Z">
              <xsl:attribute name="name">
                 <xsl:value-of select="//B[3]/C" />
              </xsl:attribute>
           </xsl:element>
        </xsl:element>
     </xsl:element>
  </xsl:template>

</xsl:stylesheet>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.