IMPORTANT:
this is not a Support Forum! Experienced users might answer from time to time questions posted here. If you need a professional and reliable answer, or if you want to report a bug, please contact Altova Support instead.

Finding Nodes between a start node and an end node. Options · View
toine
Posted: Tuesday, July 14, 2009 8:44:40 PM
Rank: Newbie

Joined: 7/14/2009
Posts: 5
Location: Montreal, Canada
I have an XML document that has the following basic structure:

<section id="1">
<...>
<...>
</section>
<section id="2">
<...>
<...>
</section>
<section id="3">
<...>
<...>
</section>
...


Is there a way using XPath or XQuery to find all the nodes that are between a start id and an end id? For example, In my XSLT I want to use the following construct: document("docpath")//id("1-3") to load an entire section of the other document that is between the start and end nodes.
Thanks in advance
paul
Posted: Wednesday, July 15, 2009 5:12:19 AM
Rank: Advanced Member

Joined: 9/9/2005
Posts: 483
Location: AT
Hello,

If I am understanding you correctly then something like this should do the trick:

//section[@id > 0 and @id < 4]//*
toine
Posted: Wednesday, July 15, 2009 12:49:37 PM
Rank: Newbie

Joined: 7/14/2009
Posts: 5
Location: Montreal, Canada
Thanks for the reply Paul.

I forgot to mention that the id's for the document are not necessarily sequential (or even necessarily integers for that matter. The id attribute is of type xs:id) So my document can look something like this:

<section id="1">
<...>
<...>
</section>
<section id="2">
<...>
<...>
</section>
<section id="5">
<...>
<...>
</section>

<section id="3">
<...>
<...>
</section>

This is due to the fact that users can modify the document. We really need to be able to find the nodes that are physically between the start node and the end node. (We have a system where we generate web pages based on these xml files. Sections of other documents can be viewed from within the current document in a kind of folding panel. The client would like to define these "include links" by defining a start and endpoint so that subsequent modifications to the document (ie: a new section being added) are included without having to modify the original link. Does that make sense?)

I don't know if this is even possible. The closest we have come is by passing a list of id's to the id function like so: id(1;2;5;3). This is close to what we want, but not exactly what we need.

thanks again.
vlad
Posted: Thursday, July 16, 2009 10:57:07 AM
Rank: Advanced Member

Joined: 12/13/2005
Posts: 2,856
Location: Mauritius
If I understand you properly you have an id for the first and last section and need to find all sections between them?

You can try to use position() function for this. For example, provided that the first section has id = 5 and last id = 3

some-parent-element/section[@id = 5]/position() gives you a position of the first section

some-parent-element/section[@id = 3]/position() of a second one

and then you use them to filter all sections within (by using variables or directly using statements above)

some-parent-element/section[position()>= $from and position() <= $till]
toine
Posted: Thursday, September 17, 2009 3:05:29 PM
Rank: Newbie

Joined: 7/14/2009
Posts: 5
Location: Montreal, Canada
vlad wrote:
If I understand you properly you have an id for the first and last section and need to find all sections between them?

You can try to use position() function for this. For example, provided that the first section has id = 5 and last id = 3

some-parent-element/section[@id = 5]/position() gives you a position of the first section

some-parent-element/section[@id = 3]/position() of a second one

and then you use them to filter all sections within (by using variables or directly using statements above)

some-parent-element/section[position()>= $from and position() <= $till]


Thanks for the response Vlad, and sorry for the delay in responding. This solution looks like it could work. I did find another solution that worked for us as well. In essence, we did something like this:

([@SectionId]=$From]/following-sibling::element()) intersect ([@SectionId]=$To]/preceding-sibling::element())

So we generated a node set from the start element and all its following siblings and another node set from the end element and all its preceding siblings. Then we used the intersect function to give us the correct node set. (I simplified the XPath above for clarity. You need to add the start and end nodes to either side of the intersect to have them included.)
Martin Honnen
Posted: Friday, September 18, 2009 10:58:40 AM
Rank: Advanced Member

Joined: 6/10/2007
Posts: 36
There are also the operators << and >> in XPath 2.0 that you can use as they can be applied to nodes to check whether one is before or after another:
Code:
<xsl:variable name="s1" select="//section[@SectionId = $From]"/>
<xsl:variable name="s2" select="//section[@SectionId = $To]"/>
<xsl:variable name="sections"
  select="//section[. is $s1 or . is $s2 or ($s1 << . and . << $s2)]"/>
Users browsing this topic
guest

Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Use of the Altova User Forum(s) is governed by the Altova Terms of Use.