Issue Details (XML | Word | Printable)

Key: JAXEN-24
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Unassigned
Reporter: Christian Nentwich
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
jaxen

preceding axis fails to report reverse document order

Created: 13/Apr/04 12:40 PM   Updated: 12/Apr/05 01:15 PM
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 1.1

Time Tracking:
Not Specified

File Attachments: 1. Java Source File PrecedingAxisIterator.java (7 kB)



 Description  « Hide
From: Anna Afonchenko <anna@ubaccess.com>
To: jaxen-interest@lists.codehaus.org

I am using Jaxen to evaluate XPath expressions in Java (JDOM).
I encountered problems when comparing results returned by jaxen with
results returned by other XPath implementation - I was using Saxon.
Here is my example:
<html>
<head>
</head>
<body>
<p>
<span>text1</span>
</p>
<div>text2</div>
</body>
</html>

I want to get the first preceding element of the div element.
I apply the following XPath - //div/preceding::*[1]
Saxon results in span element matched.
Jaxen results in p element matched.

What I want is the span element.



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Christian Nentwich added a comment - 13/Apr/04 12:41 PM
This looks similar to JAXEN-21, but it isn't.. JAXEN-21 is actually misreported.

Here is some code that reproduces this issue:

import java.io.StringReader;
import java.util.Iterator;
import java.util.List;

import org.jaxen.jdom.JDOMXPath;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

public class TestJ {

public static void main(String[] args) throws Exception { XMLOutputter outputter = new XMLOutputter(); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build( new StringReader( new String("<html><head> </head> <body> <p> <span> text1 </span> </p> <div> text2 </div> </body> </html>"))); JDOMXPath query = new JDOMXPath("//div/preceding::*"); List set = query.selectNodes(doc); for (Iterator iter=set.iterator();iter.hasNext();) System.out.println(iter.next()); outputter.output(set, System.out); }
}


Elliotte Rusty Harold added a comment - 14/Jan/05 07:54 AM
I can reproduce this with a slightly simpler document:

<body><p><span></span></p><div></div></body>

In code (for XOM):
public void testPrecedingAxis() { Element body = new Element("body"); Element p = new Element("p"); body.appendChild(p); Element span = new Element("span"); p.appendChild(span); Element div = new Element("div"); body.appendChild(div); Nodes result = div.query("preceding::*[1]"); assertEquals(1, result.size()); assertEquals(span, result.get(0)); }


Elliotte Rusty Harold added a comment - 14/Jan/05 08:55 AM
I'm still trying to work through this one, but I think the problem is in StackedIterator, and I think this affects some other bugs as well. Specifically I think stacking the iterators is producing a breadth-first search when we need to be using a depth-first search instead.

Brian Ewins added a comment - 14/Jan/05 11:05 AM
I don't think its the stacked iterator, I think its the use of 'ChildAxisIterator' in that stack.

The correct logic for PrecedingAxis is roughly this:

public boolean hasNext() {
while (!descendantOrSelfReversed.hasNext()) {
while (!precedingSibling.hasNext()) {
if (!ancestorOrSelf.hasNext()) { return false; }
precedingSibling = ps(ancestorOrSelf.next());
}
descendantOrSelfReversed = dosr(precedingSibling.next());
}
return true;
}

public Object next() {
if (hasNext()) { return descendantOrSelfReversed.next(); }
// throw an exception otherwise
}

initializing this with empty iterators for descendantOrSelfReversed and precedingSibling. The current implementation looks to me like its not reversing descendantOrSelf, but is reversing the order in which the children are accessed on that axis.


Brian Ewins added a comment - 15/Jan/05 08:52 PM
after some headscratching I wrote this: its self contained so its simpler to see that it is correct. It passes the tests for everything but dom4j, because, as far as I can tell, that navigator reports parent(Document) as Document, not null. Leaving this for others to see in case I can't figure it out but I think its worth committing.

Brian Ewins added a comment - 18/Jan/05 08:56 PM
Elliotte, I've updated the code for the preceding, ancestor, and descendant axes, but added the test you described above for this bug afterwards. It passes, but I'd prefer if you can confirm and close this bug by just updating your 'xml' directory first? Its the very first test that runs (see top of tests.xml), I'd expect you to get later test failures for Docment node stringvalues etc.

Elliotte Rusty Harold added a comment - 19/Jan/05 08:40 AM
Yes, Brian's latest patches appear to fix this (among other issues).

Brian Ewins added a comment - 19/Jan/05 09:50 PM
Tonight I got this bug back again...with the DOM navigator. It seems the bug is intermittent and it may depend on something odd like object identities as hash keys. Commenting out the code overriding the 'preceding' axis in the DOM so it gets the new version appears to resolve the problem, but I'll need to walk the DOM code to be sure its wrong.

Brian Ewins added a comment - 19/Jan/05 10:11 PM
yep... the DOM code was wrong. Not sure why this didn't show up yesterday. Fixed.

Elliotte Rusty Harold added a comment - 12/Apr/05 07:19 AM
Hmm, this seems to have resurfaced in the DOM navigator. Will investigate further.

Elliotte Rusty Harold added a comment - 12/Apr/05 01:15 PM
I think I've got this fixed. The problem was in dom.DocumentNavigator's custom PrecedingAxisIterator. For the moment I've disabled this so a correct implementation is inherited from the superclass instead. Whether it makes sense to fix that or leave it as is remains to be seen, so I'll leave this one for now in case someone wants to revisit that.