Re: [xsl] Is this possible using XSLT?

Subject: Re: [xsl] Is this possible using XSLT?
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Mon, 3 Jul 2006 22:26:10 +0530
Hi Rob,
 Given this XML:

<foo>
  <bar leftparen="((" rightparen="" num="3" oper="*" />
  <bar leftparen="" rightparen=")" num="2" oper="-" />
  <bar leftparen="" rightparen=")" num="2" />
</foo>

The following stylesheet:

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

<xsl:output method="xml" indent="yes" />

<xsl:template match="/foo">
 <foo>
   <xsl:for-each select="bar[contains(@leftparen,'(')]">
     <xsl:call-template name="XYZ">
       <xsl:with-param name="elem" select="." />
       <xsl:with-param name="x" select="string-length(@leftparen)" />
     </xsl:call-template>
   </xsl:for-each>
 </foo>
</xsl:template>

<xsl:template name="XYZ">
 <xsl:param name="elem" />
 <xsl:param name="x" />

 <paren>
   <xsl:choose>
     <xsl:when test="$x &gt; 1">
       <xsl:call-template name="XYZ">
         <xsl:with-param name="elem" select="$elem" />
         <xsl:with-param name="x" select="$x - 1" />
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:element name="{name($elem)}">
         <xsl:copy-of select="$elem/@*[(name() != 'leftparen') and
(name() != 'rightparen')]" />
       </xsl:element>
       <xsl:call-template name="PQR">
         <xsl:with-param name="nodeset"
select="$elem/following-sibling::bar" />
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
 </paren>
 <xsl:if test="$x = 1">
   <xsl:variable name="X"
select="$elem/following-sibling::bar[contains(following-sibling::*[1]/@leftparen,
'(') or not(following-sibling::*[1])]" />
   <xsl:element name="{name($X)}">
     <xsl:copy-of select="$X/@*[(name() != 'leftparen') and (name()
!= 'rightparen')]" />
   </xsl:element>
 </xsl:if>
</xsl:template>

<xsl:template name="PQR">
 <xsl:param name="nodeset" />

 <xsl:if test="($nodeset[1]/@leftparen = '') and
($nodeset[2]/@leftparen = '')">
   <xsl:element name="{name($nodeset[1])}">
     <xsl:copy-of select="$nodeset[1]/@*[(name() != 'leftparen') and
(name() != 'rightparen')]" />
   </xsl:element>
   <xsl:call-template name="PQR">
     <xsl:with-param name="nodeset" select="$nodeset[position() &gt; 1]" />
   </xsl:call-template>
 </xsl:if>
</xsl:template>

</xsl:stylesheet>

produces output:

<foo>
  <paren>
     <paren>
        <bar num="3" oper="*"/>
        <bar num="2" oper="-"/>
     </paren>
     <bar num="2"/>
  </paren>
</foo>

(This is what you wanted)

I hope you can take this stylesheet as a starting point, and tinker with it.

Regards,
Mukul

On 7/3/06, Rob Allen <rallen3333@xxxxxxxxx> wrote:
Hello,

Is it possible to get XSLT to transform XML that looks
like this:
<foo>
   <bar leftparen="((" rightparen="" num="3" oper="*"
/>
   <bar leftparen="" rightparen=")" num="2" oper="-"
/>
   <bar leftparen="" rightparen=")" num="2" />
</foo>

into something that looks like this:
<foo>
  <paren>
    <paren>
      <bar num="3" oper="*"/>
      <bar num="2" oper="-"/>
    </paren>
    <bar num="2"/>
  </paren>
</foo>

"paren" elements are opened and closed based on the
number of '(' in each element's leftparen and
rightparen attributes.
Can anyone help?
Thanks,

Rob

Current Thread