- From: John Boyer <boyerj@ca.ibm.com>
- Date: Mon, 10 Oct 2011 16:31:58 -0700
- To: public-forms@w3.org
- Message-ID: <OFD4A44E21.7ED53337-ON88257925.007DE26B-88257925.00814681@ca.ibm.com>
1) Combining @iterate with @while and @if
Not that I like it overly much, but the spec language for the while
attribute indicates that an if attribute is evaluated at each iteration of
the while loop, so the 'if' is inside the while loop execution.
For consistency and ease of implementation, it is tempting then to say
that @iterate obtains a nodeset and then for each node, the action bearing
@iterate is executed, excluding the @iterate but including any @while and
@if attributes on it.
However, currently the if and while attributes are evaluated in the
in-scope evaluation context of the containing element, so we would have to
amend that language to say that if and while are evaluated in the context
as set by iterate. Otherwise, it would be very weird to authors to say
that if and while occur for each node of the iterate but have no way to
access that iteration node and are evaluated in a context that is outside
of the iteration nodeset.
Due to the possibilities for confusion, we could say that an
implementation MAY support iterate in combination with the other
attributes, so that we can say how it should be have if supported without
forcing all implementers to get there.
2) Deleting nodes from the nodeset
I am hitting lots of really reasonable cases where I am deleting nodes
from the nodeset over which I am currently iterating. This includes not
only the current iteration node, but possibly successors.
It should be legal to delete the iteration node and, at least in the same
delete action, to delete successors of that node.
3) Dynamically adding to the iterate nodeset
I am hitting a lot of cases where I legitimately want to add nodes that
*would* match the @iterate expression if it were re-evaluated, and in the
cases I'm hitting, I definitely don't want to include those nodes in the
iteration because they are predecessors to the current iteration node. In
other words, I don't even have to use a predicate to achieve this effect
of not wanting to include these nodes.
It seems better to say, as in #1 above, that the @iterate nodeset is
obtained once, and then that nodeset is used in a for-each. When we get
to a particular node, if it is "stale" because it has been deleted, then
skip it. If other nodes are added to the context in which the iteration
nodeset was obtained, they are not included in the for-each behavior.
As a concrete example, here is the pseudo-code for a simple "selection"
sorting routine:
iterate nodeset "employees/person"
maxvalue = ./name
iterate nodeset "next-sibling::*" {
If compare(./name, maxvalue) > 0
maxvalue = ./name
}
insert context=".." origin="person[name=maxvalue]"
delete nodeset="(self::* | next-sibling::*)[name=maxvalue]"
The penultimate insert adds new nodes to the beginning of the employee
list that match the outer iterate loop's nodeset, but clearly the
iteration should not take these new nodes into the iteration. The final
line deletes the copies of the nodes inserted. If there are duplicate key
values (e.g. sorting by first name), then this operation will remove one
or more nodes from future steps of the outer loop iteration. Also, when
the maxvalue is the current iteration node, then the final delete also
eliminates the current iteration node. In the duplicate key case, we need
the delete to remove all matched nodes even though the first node it
removes is the evaluation context node for the delete action. This
should not be a problem because all XPaths of the delete action are
evaluated before the first node deletion takes place.
Cheers,
John M. Boyer, Ph.D.
Distinguished Engineer, IBM Forms and Smarter Web Applications
IBM Canada Software Lab, Victoria
E-Mail: boyerj@ca.ibm.com
Blog: http://www.ibm.com/developerworks/blogs/page/JohnBoyer
Blog RSS feed:
http://www.ibm.com/developerworks/blogs/rss/JohnBoyer?flavor=rssdw
Received on Monday, 10 October 2011 23:32:30 UTC