Re: [xsl] [xslt] xslt problem

Subject: Re: [xsl] [xslt] xslt problem
From: Ronan Klyne <ronan.klyne@xxxxxxxxxxx>
Date: Thu, 19 Mar 2009 09:20:17 +0000
Michalmas wrote:
> Hi guys,
> 
> I made small error in the example XMLs, actually the main problem i
> had i skipped.
> 
> In the result XML, i need to get referance of attribute space of
> previous node (something like preceding-sibling). If the previous node
> doens't have it, i need to go further back until i find it or until
> the beginning of XML.
> 
> Correct result XML would be:
> <example>
>   <someNode>
>           <value>asas</value>
>           <name>asas</name>
>           <space>12</space>
>   </someNode>
>   <interestingNode>
>           <con>someString</con>
>           <follow>
>                   <return>0</return>
>           </follow>
>           <space>5</space>
>   </interestingNode>
> 
>   <node1 space="12">1</node1> <!-- HERE space attribute  -->
>   <node2 space="12">2</node2>
>   <node3 space="12">3</node3>
>   <node4 space="12">4</node4>
> </example>

The key difference here will be to use the xpath
'preceding-sibling::*[space]/space[1]' to pick the right space tag. The
logic here is as follows:
1) 'preceding-sibling::*' - get all preceding siblings of the current node
2) '[space]' - filter these to the ones with a 'space' child.
3) '/space[1]' - get the first 'space' child.

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

<xsl:template match="example">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="interestingNode[con='someString']">
  <interestingNode>
    <xsl:copy-of select="con" />
    <follow>
      <return>0</return>
    </follow>
    <xsl:copy-of select="space" />
  </interestingNode>
  <xsl:variable name="space"
select="preceding-sibling::*[space]/space[1]" />
  <xsl:for-each select="follow/*">
    <xsl:copy>
      <xsl:attribute name="space" select="$space" />
      <xsl:copy-of select="node()" />
    </xsl:copy>
  </xsl:for-each>
</xsl:template>

<xsl:template match="*">
  <xsl:copy-of select="." />
</xsl:template>

</xsl:stylesheet>



> On Thu, Mar 19, 2009 at 10:00 AM, Michael Kay <mike@xxxxxxxxxxxx> wrote:
>> Not the most imaginative title for a post.
>>
>>> <example>
>>>     <someNode>
>>>             <value>asas</value>
>>>             <name>asas</name>
>>>             <space>12</space>
>>>     </someNode>
>>>     <interestingNode>
>>>             <con>someString</con>
>>>             <follow>
>>>                     <node1>1</node1>
>>>                     <node2>2</node2>
>>>                     <node3>3</node3>
>>>                     <node4>4</node4>
>>>             </follow>
>>>             <space>5</space>
>>>     </interestingNode>
>>> </example>
>>>
>>>
>>> Now i want to transform it to:
>>>
>>> <example>
>>>     <someNode>
>>>             <value>asas</value>
>>>             <name>asas</name>
>>>             <space>12</space>
>>>     </someNode>
>>>     <interestingNode>
>>>             <con>someString</con>
>>>             <follow>
>>>                     <return>0</return>
>>>             </follow>
>>>             <space>5</space>
>>>     </interestingNode>
>>>
>>>     <node1 space="5">1</node1>
>>>     <node2 space="5">2</node2>
>>>     <node3 space="5">3</node3>
>>>     <node4 space="5">4</node4>
>>> </example>
>>>
>>>
>>> The changes are:
>>> - when interestingNode is found, we check the con value
>>> - if con value conforms someString, then we make
>>> transformation of this part by:
>>>     - evrything in follow node is moved outside interestingNode
>>>     - follow node gets one child return
>>>     - all nodes moved outside get an attribute space with
>>> value specified in original node
>>>
>> That seems to be a rule you can translate directly into XSLT:
>>
>> <xsl:template match="interestingNode[con='someString']">
>>  <xsl:copy>
>>    <xsl:copy-of select="con"/>
>>    <follow><return>0</return></follow>
>>    <xsl:copy-of select="space"/>
>>  </xsl:copy>
>>  <xsl:variable name="space" select="space"/>
>>  <xsl:for-each select="follow/*">
>>    <xsl:copy>
>>      <xsl:attribute name="space" select="$space"/>
>>      <xsl:copy-of select="child::node()"/>
>>    </xsl:copy>
>>  </xsl:for-each>
>> </xsl:template>
>>
>> Michael Kay
>> http://www.saxonica.com/
> 
> 


-- 
Ronan Klyne
Business Collaborator Developer
Tel: +44 01189 028518
ronan.klyne@xxxxxxxxxxx
www.groupbc.com

Current Thread