[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Re: [xsl] [xslt] enhance match condition for next node referance
Subject: Re: [xsl] [xslt] enhance match condition for next node referance From: Ronan Klyne <ronan.klyne@xxxxxxxxxxx> Date: Thu, 19 Mar 2009 15:21:00 +0000 |
Michalmas wrote: > Hi, > > And what about problem when next node (after the interesting node) > must satisfy some condition? Let's say that node after interestingNode > must be exit (and only this node can be there). And all nodes are > encapsulated in one more, like shown below: > <encapsulating> > <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> > <exit /> <!-- HERE the condition --> > </encapsulating> The XPath "interestingNode[follow/test and con='someString']" will match any interestingNode element with a test element inside a follow child, and the correct text in it's "con" child. If the node after must be an 'exit' node, then this would be specified as "following-sibling::node()[1][self::exit]". The "[1]" is important - it ensures that we are looking at the first following sibling, then in the condition, we check that this node is an 'exit' node. "following-sibling::exit" is the wrong way to do it, but I point it out because it looks OK - this would look at all following siblings (not just the immediate one) and give you all the ones that were 'exit' elements. Putting this all together, we get: "interestingNode[following-sibling::node()[1][self::exit] and follow/test and con='someString']" Enjoy, Ronan > On Thu, Mar 19, 2009 at 3:27 PM, Ronan Klyne <ronan.klyne@xxxxxxxxxxx> wrote: >> 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 > > -- Ronan Klyne Business Collaborator Developer Tel: +44 01189 028518 ronan.klyne@xxxxxxxxxxx www.groupbc.com
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] [xslt] enhance match cond, Michalmas | Thread | Re: [xsl] [xslt] enhance match cond, David Carlisle |
Re: [xsl] [xslt] enhance match cond, Michalmas | Date | Re: [xsl] [xslt] enhance match cond, David Carlisle |
Month |