|
Re: Additional Xpath Functions [message #522342 is a reply to message #520438] |
Mon, 22 March 2010 12:55 |
Paul Elder Messages: 849 Registered: July 2009 |
Senior Member |
|
|
Chris:
I'm all for adding more functions. But, lets see if we can get things
working sooner that that...
Your iterate statement is:
> <c:iterate select='$app//role[not(following::role = .)]'>
The comparison:
following::role = .
is defined by this somewhat convoluted section of the XPath 1.0 spec:
http://www.w3.org/TR/xpath/#booleans
In particular, since following::role and . are both 'node sets', the
result if the comparison is defined to be:
"...the comparison will be true if and only if there is a node in the
first node-set and a node in the second node-set such that the result of
performing the comparison on the string-values of the two nodes is true."
Since the above is doing string-value comparisons on these elements, I
assume that <role> elements are simple types. (I.e. the look like
<role>foo</role>, and have not nested content or attributes).
So, you are trying to get all distinct values of a simple element 'role'
(your implementation would be getting the last distinct value, but I'd
guess you don't care.) The XPath expression you have used, however, is
fairly expensive.
First, // traverses EVERY node in the DOM tree below $app. If 'role'
elements are at different levels in the tree, then this is unavoidable.
But, if <role> elements are always at a specific level in the document,
then expressions like $app/*/role or $app/*/*/role will be more efficient.
Second, following::role = . is O(n) on the number of <role> nodes in the
document tree, since at each found <role> element, the XPath engine must
find all following <role> elements. Combine this with the surrounding
iteration at O(n) (actually, it is linear on the number of elements in
the tree, since you use //), you get the loop costing at least O(n^2).
With lots of <role> elements in the model, this can get pretty slow.
Here's a suggestion. Use the sort function and then do 'control break'
processing on the result...
<c:setVariable var="lastRole" select=" '' "/> <%-- or use some value
guaranteed not to be a role value --%>
<c:iterate select="sort($app//role)" var="role">
<c:if select="not($lastRole = $role)">
... process role ...
<c:setVariable var="lastRole" select="string($role)"/>
</c:if>
</c:iterate>
The sort is a standard quick-sort, so worst case is O(n.log(n)), so the
loop is costing something near O(n.log(n)) - much better than O(n^2).
I'm going to investigate the ClassCastException - I don't think if
should be happening. Can enter a JET bug describing how to reproduce?
https://bugs.eclipse.org/bugs/enter_bug.cgi?bug_severity=nor mal&bug_status=NEW&component=Jet&form_name=enter _bug&product=M2T
And, if you still want those XPath 2.0 functions, please file an
enhancement bugzilla:
https://bugs.eclipse.org/bugs/enter_bug.cgi?bug_severity=enh ancement&bug_status=NEW&component=Jet&form_name= enter_bug&product=M2T
Paul
|
|
|
|
Powered by
FUDForum. Page generated in 0.03432 seconds