Re: [xsl] automatic creation of nested elements

Subject: Re: [xsl] automatic creation of nested elements
From: "Ganesh Babu N" <nbabuganesh@xxxxxxxxx>
Date: Thu, 4 Dec 2008 17:33:14 +0530
Dear All,

Input XML:

  <map>
     <source>bib-reference</source>
     <source>@id</source>
     <source>@class</source>
     <target>reference/citation</target>
     <target>@id</target>
     <target>@type</target>
  </map>

Required output:

<xsl:template match="bib-reference">
     <xsl:element name="reference">
       <xsl:element name="citation">
        <xsl:attribute name="id">
           <xsl:value-of select="@id"/>
        </xsl:attribute>
        <xsl:attribute name="type">
           <xsl:value-of select="@class"/>
        </xsl:attribute>
        <xsl:apply-templates/>
     </xsl:element>
  <xsl:element>
 </xsl:template>



Stylesheet used:

<xsl:template match="map">
               <xsl:if test="count(child::*) &gt; 3 and
not(starts-with(source,'@'))">
                       <mac:template match="{source[1]}">
                               <xsl:variable name="nestedele"
select="tokenize(target[1],'/')"/>
                               <xsl:call-template name="buildtree">
                                       <xsl:with-param name="position"
select="1"/>
                               </xsl:call-template>
                       </mac:template>
               </xsl:if>
       </xsl:template>
       <xsl:template name="buildtree">
               <xsl:param name="position"/>
               <xsl:variable name = "element"
select="tokenize(target[1],'/')[$position]"/>
               <xsl:if test = "string($element)">
                       <mac:element name="{$element}">
                              <xsl:for-each select="target">
                               <xsl:if test="not($position = 1) and
exists(source[2])">
                                       <mac:attribute
name="{substring-after(target[$position],'@')}">
                                               <mac:value-of
select="{source[$position]}"/>
                                       </mac:attribute>
                               </xsl:if>
                              </xsl:for-each>
                               <xsl:call-template name="buildtree">
                                       <xsl:with-param name="position"
select="$position +1"/>
                               </xsl:call-template>
                                <mac:apply-templates/>
                       </mac:element>
               </xsl:if>
       </xsl:template>


Ouput with the above stylesheet:

<xsl:template match="bib-reference">
     <xsl:element name="reference">
       <xsl:element name="citation">
        <xsl:attribute name="id">
           <xsl:value-of select="@id"/>
        </xsl:attribute>
        <xsl:apply-templates/>
     </xsl:element>
   <xsl:apply-templates/>
  <xsl:element>
 </xsl:template>

In the resultant output I am getting template only for first attribute
and 2nd attribute is missing.
<xsl:apply-templates> is appearing twice resulting duplication of the
content. Please suggest how to get the required output.

Thanks & Regards,
Ganesh



On Thu, Dec 4, 2008 at 2:58 PM, vasu chakkera <vasucv@xxxxxxxxx> wrote:
>
> You have to be clear on your problem. Best way is to give example of your
> XML and xsl and your output and tell where in output you see the problem
> Most people in the list are very generous and take extra pains in trying to
> understand the problem and suggest a solution. All they are doing is trying
> to help you. So, from your side, its always a good practice to really put
> down the problem as clear as possible so that its easy for people to answer
> ( without guessing what your problem could be )
>
> Cheers.
> Vasu
>
> -------Original Message-------
>
> From: Ganesh Babu N
> Date: 04/12/2008 06:15:31
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re: [xsl] automatic creation of nested elements
>
> Dear all,
>
> I am facing two problems in the given stylesheet.
>
> 1. <xsl:apply-templates/> is coming in both the elements resulting
> Duplication of the content.
> 2. Multiple attributes are not getting created. Only single
> Attributing is getting created.
>
> Please guide me how to achieve the above two points.
>
> Regards,
> Ganesh
>
>
> On Mon, Dec 1, 2008 at 8:22 PM, Vasu Chakkera <vasucv@xxxxxxxxx> wrote:
>> Try the below. ( I just carried it along the way of creating the
>> children recursively from your target. Add your attributes etc as
>> necessary ). Just changed from where you had a for-each. Dint check
>> the other parts of your code. The below produces the result you
>> wanted.
>>
>> <xsl:template match="map">
>> <xsl:if test="count(child::*) &gt; 3 and not(starts-with(source,'@'))">
>> <mac:template match="{source[1]}">
>> <xsl:variable name="nestedele"
>> select="tokenize(target[1],'/')"/>
>> <xsl:call-template name="buildtree">
>> <xsl:with-param name="position" select="1"/>
>> </xsl:call-template>
>> </mac:template>
>> </xsl:if>
>> </xsl:template>
>> <xsl:template name="buildtree">
>> <xsl:param name="position"/>
>> <xsl:variable name = "element" select="tokenize(target[1],'/')[$position]
> />
>> <xsl:if test = "string($element)">
>> <mac:element name="{$element}">
>> <xsl:if test="not($position = 1) and exists(source[2])">
>> <mac:attribute name="{substring-after(target[$position],'@')}">
>> <mac:value-of select="{source[$position]}"/>
>> </mac:attribute>
>> </xsl:if>
>> <xsl:call-template name="buildtree">
>> <xsl:with-param name="position" select="$position +1"/>
>> </xsl:call-template>
>> <mac:apply-templates/>
>> </mac:element>
>> </xsl:if>
>> </xsl:template>
>>
>> hth
>> Vasu C
>>
>> 2008/12/1 Ganesh Babu N <nbabuganesh@xxxxxxxxx>:
>>> Input XML:
>>>
>>> <map>
>>> <source>bib-reference</source>
>>> <source>@id</source>
>>> <target>reference/citation</target>
>>> <target>@id</target>
>>> </map>
>>>
>>> Required output:
>>> <xsl:template match="bib-reference">
>>> <xsl:element name="reference">
>>> <xsl:element name="citation">
>>> <xsl:attribute name="id">
>>> <xsl:value-of select="@id"/>
>>> </xsl:attribute>
>>> <xsl:apply-templates/>
>>> </xsl:element>
>>> <xsl:element>
>>> </xsl:template>
>>>
>>> My XSLT:
>>> <xsl:template match="map">
>>> <xsl:when test="count(child::*) &gt; 3 and not(starts-with(source,'@'))">
>
>>> <mac:template match="{source[1]}">
>>> <xsl:variable name="nestedele"
>>> select="tokenize(target[1],'/')"/>
>>> <xsl:for-each select="$nestedele">
>>> <xsl:variable name="tem" select="."/>
>>> <mac:element name="{$tem}">
>>> <xsl:for-each select="target">
>>> <xsl:variable name="pos" select="position()"/>
>>> <xsl:if test="not(position()=1) and exists(../source[2])">
>>> <mac:attribute name="{substring-after(.,'@')}">
>>> <mac:value-of select="{../source[$pos]}"/>
>>> </mac:attribute>
>>> </xsl:if>
>>> </xsl:for-each>
>>> <mac:apply-templates/>
>>> </mac:element>
>>> </xsl:for-each>
>>> </mac:template>
>>> </xsl:when>
>>> </xsl:template>
>>>
>>> This will create one element after the other but it won't create the
>>> nested one. In a result for bib-reference, two elements will be
>>> created with same content. Which is a wrong one. Please guide me how
>>> to generate the nested element structure.
>>>
>>> Regards,
>>> Ganesh
>>>
>>>
>>
>>
>>
>> --
>> Vasu Chakkera
>> Numerical Algorithms Group Ltd.
>> Oxford
>> www.vasucv.com

Current Thread