Details
-
Bug
-
Status: Resolved
-
Resolution: Fixed
-
1.4.x
-
None
-
None
-
Operating System: All
Platform: All
-
15983
Description
Somewhere in the recent changes something has changed that
has exposed a small bug with Namespaces and pointed out
a second potential problem where namespace searches appear
to use nodes from parent elements even though the particular
namespace prefix has already been defined lower down in the
structure.
The small bug is that unions of Namespaces don't appear to
always work correctly :
z.xml :
<?xml version="1.0" encoding="UTF-8"?>
<foo:Root xmlns:bar="http://example.org/bar" xmlns:foo="http://example.org/foo">
<bar:Something xmlns:bar="http://example.org/bar"
xmlns:foo="http://example.org/foo">
</bar:Something>
</foo:Root>
Using XPathWrapper from Oct 21 interim release:
berin@zeus:bin$ ./XPathWrapper /tmp/z.xml
/foo:Root/bar:Something/namespace::bar[1] "parent::node()/namespace::* |
self::node()"
the result set has 5 strings
item 1= "http://www.w3.org/XML/1998/namespace"
item 2= "http://example.org/bar"
item 3= "http://example.org/foo"
item 4= "http://example.org/bar"
item 5= "http://example.org/foo"
—
Using XPathWrapper from CVS (roughly 5 days old)
./XPathWrapper /tmp/z.xml /foo:Root/bar:Something/namespace::bar[1]
"parent::node()/namespace::* | self::node()"
the result set has 6 strings
item 1= "http://example.org/bar"
item 2= "http://example.org/foo"
item 3= "http://www.w3.org/XML/1998/namespace"
item 4= "http://example.org/bar"
item 5= "http://example.org/foo"
item 6= "http://example.org/bar"
—
In the newer code, the union is not working correctly,
and xmlns:bar is re-added to the node-set.
The findNamespace functions sets the subQueryResult as
in document order, so the union function takes some
shortcuts, sees that the final node in the list is "lesser" than
the node being added so just adds it. In fact, findNamespace
is not returning nodes in document order, so the shortcut
is incorrect.
Have attached a patch that fixed the problem on my system
by re-ordering the findNamespace loops to put the
nodes in document order correctly.
—
The other problem is that I don't think (I could be
wrong?) that all these namespaces should be returned.
For example, the conext node expression I use above
returns two nodes, and it should return 1 (thus the
[1] expression to select the first found).
According to the XPath standard an element has
"a namespace node:
- for every attribute on the element whose name starts
with xmlns:;
- for every attribute on an ancestor element whose name
starts with xmlns: _unless the element itself or a
nearer ancestor redeclares the prefix_;
..."
(emphasis mine).
So for the expression:
/foo/bar/namespace::bart
only one node should ever be returned.
Not too sure what the best solution would be if my
interpretation is correct. Could :
- Search the subQueryResult list for an existing
element that defines the same prefix (inneficient
for longer lists as the list is sorted in document
order not in namespace order, so there is no way
to shortcut in the search).
- Create a temporary list sorted in namespace prefix
order (with default at front) and then do a binary
search to see if the prefix is defined.
- Could use an existing namespace handling structure
to insert the namespaces and then pull back those
visible. (Had a quick look and couldn't see anythign
that would map easily, but am not familiar enough with
all the code.)