File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes JSP and the fly likes Is there a way to compare 2 xpaths in JSTL? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSP
Bookmark "Is there a way to compare 2 xpaths in JSTL?" Watch "Is there a way to compare 2 xpaths in JSTL?" New topic
Author

Is there a way to compare 2 xpaths in JSTL?

Benjamin Weaver
Ranch Hand

Joined: Apr 08, 2003
Posts: 161
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!
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

Yes, but the compare-for-equals operator in XPath is just = and not ==.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

Oh, and you don't need those square brackets either.
Benjamin Weaver
Ranch Hand

Joined: Apr 08, 2003
Posts: 161
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
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

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
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

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

Joined: Apr 08, 2003
Posts: 161
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

Joined: Apr 08, 2003
Posts: 161
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

Joined: Apr 08, 2003
Posts: 161
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
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Is there a way to compare 2 xpaths in JSTL?