Re: [xsl] [xslt] xslt problem

Subject: Re: [xsl] [xslt] xslt problem
From: Michalmas <michalmas@xxxxxxxxx>
Date: Thu, 19 Mar 2009 15:22:52 +0100
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>

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>
>> B  <someNode>
>> B  B  B  B  B  <value>asas</value>
>> B  B  B  B  B  <name>asas</name>
>> B  B  B  B  B  <space>12</space>
>> B  </someNode>
>> B  <interestingNode>
>> B  B  B  B  B  <con>someString</con>
>> B  B  B  B  B  <follow>
>> B  B  B  B  B  B  B  B  B  <return>0</return>
>> B  B  B  B  B  </follow>
>> B  B  B  B  B  <space>5</space>
>> B  </interestingNode>
>>
>> B  <node1 space="12">1</node1> <!-- HERE space attribute B -->
>> B  <node2 space="12">2</node2>
>> B  <node3 space="12">3</node3>
>> B  <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">
> B <xsl:apply-templates/>
> </xsl:template>
>
> <xsl:template match="interestingNode[con='someString']">
> B <interestingNode>
> B  B <xsl:copy-of select="con" />
> B  B <follow>
> B  B  B <return>0</return>
> B  B </follow>
> B  B <xsl:copy-of select="space" />
> B </interestingNode>
> B <xsl:variable name="space"
> select="preceding-sibling::*[space]/space[1]" />
> B <xsl:for-each select="follow/*">
> B  B <xsl:copy>
> B  B  B <xsl:attribute name="space" select="$space" />
> B  B  B <xsl:copy-of select="node()" />
> B  B </xsl:copy>
> B </xsl:for-each>
> </xsl:template>
>
> <xsl:template match="*">
> B <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>
>>>> B  B  <someNode>
>>>> B  B  B  B  B  B  <value>asas</value>
>>>> B  B  B  B  B  B  <name>asas</name>
>>>> B  B  B  B  B  B  <space>12</space>
>>>> B  B  </someNode>
>>>> B  B  <interestingNode>
>>>> B  B  B  B  B  B  <con>someString</con>
>>>> B  B  B  B  B  B  <follow>
>>>> B  B  B  B  B  B  B  B  B  B  <node1>1</node1>
>>>> B  B  B  B  B  B  B  B  B  B  <node2>2</node2>
>>>> B  B  B  B  B  B  B  B  B  B  <node3>3</node3>
>>>> B  B  B  B  B  B  B  B  B  B  <node4>4</node4>
>>>> B  B  B  B  B  B  </follow>
>>>> B  B  B  B  B  B  <space>5</space>
>>>> B  B  </interestingNode>
>>>> </example>
>>>>
>>>>
>>>> Now i want to transform it to:
>>>>
>>>> <example>
>>>> B  B  <someNode>
>>>> B  B  B  B  B  B  <value>asas</value>
>>>> B  B  B  B  B  B  <name>asas</name>
>>>> B  B  B  B  B  B  <space>12</space>
>>>> B  B  </someNode>
>>>> B  B  <interestingNode>
>>>> B  B  B  B  B  B  <con>someString</con>
>>>> B  B  B  B  B  B  <follow>
>>>> B  B  B  B  B  B  B  B  B  B  <return>0</return>
>>>> B  B  B  B  B  B  </follow>
>>>> B  B  B  B  B  B  <space>5</space>
>>>> B  B  </interestingNode>
>>>>
>>>> B  B  <node1 space="5">1</node1>
>>>> B  B  <node2 space="5">2</node2>
>>>> B  B  <node3 space="5">3</node3>
>>>> B  B  <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:
>>>> B  B  - evrything in follow node is moved outside interestingNode
>>>> B  B  - follow node gets one child return
>>>> B  B  - 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']">
>>> B <xsl:copy>
>>> B  B <xsl:copy-of select="con"/>
>>> B  B <follow><return>0</return></follow>
>>> B  B <xsl:copy-of select="space"/>
>>> B </xsl:copy>
>>> B <xsl:variable name="space" select="space"/>
>>> B <xsl:for-each select="follow/*">
>>> B  B <xsl:copy>
>>> B  B  B <xsl:attribute name="space" select="$space"/>
>>> B  B  B <xsl:copy-of select="child::node()"/>
>>> B  B </xsl:copy>
>>> B </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