Re: [xsl] [xslt] xslt problem

Subject: Re: [xsl] [xslt] xslt problem
From: Ronan Klyne <ronan.klyne@xxxxxxxxxxx>
Date: Thu, 19 Mar 2009 14:27:25 +0000
Michalmas wrote:
> Hi,
> 
> one more question - how to enhance the condition in template to check
> if among the children nodes there is <test> node. So, it should work
> for:
> 
> <interestingNode>
>             <con>someString</con>
>             <follow>
>                     <node1>1</node1>
>                     <test>2</test> <!-- HERE we have required node -->
>                     <node3>3</node3>
>                     <node4>4</node4>
>             </follow>
>             <space>5</space>
>     </interestingNode>
> 
> but not for:
> 
> <interestingNode>
>             <con>someString</con>
>             <follow>
>                     <node1>1</node1>
>                     <node2>2</node2>
>                     <node3>3</node3>
>                     <node4>4</node4>
>             </follow>
>             <space>5</space>
>     </interestingNode>

Change "interestingNode[con='someString']"
to "interestingNode[follow/test and con='someString']"

> 
> thanks!
> 
> On Thu, Mar 19, 2009 at 10:20 AM, Ronan Klyne <ronan.klyne@xxxxxxxxxxx> wrote:
>> 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
> 
> 


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

Current Thread