Win a copy of Learning Regular Expressions this week in the General Computing forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Liutauras Vilda
  • Campbell Ritchie
  • Tim Cooke
  • Bear Bibeault
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Knute Snortum
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Ganesh Patekar
  • Stephan van Hulst
  • Pete Letkeman
  • Carey Brown
Bartenders:
  • Tim Holloway
  • Ron McLeod
  • Vijitha Kumara

Is there a way to compare 2 xpaths in JSTL?  RSS feed

 
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In JSTL 1.1 on Tomcat 5.28,

I want to test whether 2 xpath expressions are the same. Is there a way to do that? <x:if> can surely check whether a path exists, but I want the boolean to indicate whether one xpath is the same as another xpath.

The point is to find out if a sibling element is of a certain tag type.

For example, the following code

<x:if select="$doc/ThisPath">

checks simply whether the path "$doc/ThisPath" exists

But I want to find how to do something like this:

<x:if select="[$doc/ThisPath == $doc/someParticularTag]">


Any help is appreciated!
 
Sheriff
Posts: 23714
50
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, but the compare-for-equals operator in XPath is just = and not ==.
 
Paul Clapham
Sheriff
Posts: 23714
50
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, and you don't need those square brackets either.
 
Benjamin Weaver
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Hugh,

I realise my question had a second part. Given the following code,

<x:forEach var="linePart" select="following-sibling::*" >


how would I reference the xpath of the variable linePart?

A statement like <x ut select="$linePart" /> will reference the value inside the tag. But I want just the xpath TO the tag.
 
Paul Clapham
Sheriff
Posts: 23714
50
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually now that I re-read your question I realize that I don't understand it very well. I don't understand what it means to say that two XPath expressions are "the same". It's quite possible for two XPath expressions that have different external representations to return the same nodesets. I was under the impression you just wanted to know whether two XPath expressions returned the same nodesets.

And you're asking for "the" XPath to a node? Again, there's usually more than one way to represent that. There may be a specification that describes a canonical XPath representation for a node but if there is I'm not aware of it.
 
Paul Clapham
Sheriff
Posts: 23714
50
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe I should ignore most of the question and just concentrate on the real problem, which appears to be

The point is to find out if a sibling element is of a certain tag type.

I think you should just concentrate on figuring out an XPath expression which tells you that. For example if that means "Is there a following sibling which is an ABC element?" then your XPath would be "following-sibling::ABC" which would return either the ABC element or nothing. Or if it means "Is the next sibling an ABC element?" then your XPath would be something like "following-sibling::[1][local-name()='ABC']"... I say something like because I never get those things right the first time.
 
Benjamin Weaver
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Paul,

Here's the xml (simplified). It's a spec I cannot change.

<text>
<lb n=1/>
<w>someword</w>
<w>someword</w>
<w>someword</w>
<lb n=2/>
</text>

["lb" stands for "line break." We are putting up lines of text]

The problem I face is that lb and word elements are siblings. To process all words in a given line it seems I have to do the following:

(1) <x:forEach var="line" select="...path...text/lb">

(2)<x:forEach var="linePart" select="following-sibling::*" >
[this will get ALL following siblings of the current line break down to the end of the text. But we want to exit the loop, stop processing word elements for a given line break once the NEXT LINE BREAK element is reached (in the example xml, lb n=2):

I could have used a choose/when/otherwise, but didn't feel it necessary
So the iteration I have written is below. The part I don't know how to write, where I determine whether the current sibling is in fact the next line break, is found in the first "if" statement after the foreach call.

(2) expanded:

<x:forEach var="linePart" select="following-sibling::*" >
<c:set var="stillInThisLine" value="true" scope="page" />


<x:if select="COMPARE XPATH OF CURRENT LINEPART TO LINEPATH OF NEXT LB">
<c:set var="stillInThisLine" value="false" />
</x:if>

<%--now test; if still in the current line, print out the word; otherwise don't do anything after the next lb element is reached.
--%>

<c:if test="$stillInThisLine">
<x ut select="$linePart" />
</c:if>

</x:forEach>
 
Benjamin Weaver
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, a paraphrase is easier,

1. After hitting a given line break element, I want to process only those words immediately following it.

2. FROM THE NEXT LINE BREAK ELEMENT (say lb n=2 AND FOREVER THEREAFTER, I WANT TO DO NOTHING.

3. then the outer foreach loop brings me to the next line, and steps 1 and 2 are repeated...

Here is a better xml example:

<text>
<lb n=1 />
<w>someWord</w>
<w>someWord</w>
<w>someWord</w>
<lb n=2 />
<w>someWord</w>
<w>someWord</w>
<lb n=3 />
<w>someWord</w>
<w>someWord</w>
</text>
 
Benjamin Weaver
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul, thanks again.

I have slept on this, and now it seems not so difficult a problem, using your solution.

Your second guess was the correct one: my question to be answered: "is the next sibling an element of type "lb" (line break)?"

So it seems I should loop through the words following each line break, testing each one with your call: following-sibling::[1][local-name()='w']"... As soon as I hit a following-sibling that is not a word but a line-break, indicating the next line of text, I exit the inner loop that processes the words and continue, in the outer loop to process the next line break.

I will try it out.
 
Paul Clapham
Sheriff
Posts: 23714
50
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In other words:

FOR EACH line break element,
Process the word elements up to the next line break element.

That seems to be your latest approach, which I think is better than the earlier ones. In XSLT it's preferable to write declarative algorithms (e.g. "Here's what to do for a word element") rather than procedural algorithms (e.g. "Scan the word elements and if the next element is a line break then..."). That's just the way the language works.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!