insert allows a node to be inserted into a nodeset, at a certain position. The handler has a set of default behaviours defined which creates for a very powerful and flexible action.
All of the following examples assume this initial instance data:
<instanceData xmlns="">
<list>
<y>y1</y>
<y>y2</y>
<y>y3</y>
</list>
<templates>
<x>x1</x>
</templates>
</instanceData>
The simplest form of the handler specifies a nodelist, and duplicates the last item in the list:
<xf:insert nodeset="list/y" />
The result would be:
<list>
<y>y1</y>
<y>y2</y>
<y>y3</y>
<y>y3</y>
</list>
It is also possible to indicate a position to copy the last node in the list to. The at attribute indicates which node in the nodeset to place the copied node after:
<xf:insert nodeset="list/y" at="1" />
The result would be:
<list> <y>y1</y> <y>y3</y> <y>y2</y> <y>y3</y> </list>
To place the copied node before the node referred to by @at, use the position attribute with a value of before:
<xf:insert nodeset="list/y" at="1" position="before" />
The result would be:
<list> <y>y3</y> <y>y1</y> <y>y2</y> <y>y3</y> </list>
Note that the default value for @position is after, so the following are equivalent:
<xf:insert nodeset="list/y" at="1" /> <xf:insert nodeset="list/y" at="1" position="after" />
The @at attribute is actually an XPath expression, so it is possible to calculate an insert position at run-time. The expression is evaluated in the context of the first node in the @nodeset, as illustrated by the following example:
<xf:insert nodeset="list/y" at="count(../y) - 1" position="before" />
The result would be:
<list> <y>y1</y> <y>y3</y> <y>y2</y> <y>y3</y> </list>
It is also possible to copy a node from some other location than the last node in the list, by using the origin attribute. The node could be in the target nodelist:
<xf:insert nodeset="list/y" origin="list/y[1]" />
which would give:
<list>
<y>y1</y>
<y>y2</y>
<y>y3</y>
<y>y1</y>
</list>
But the node to copy need not be in the nodeset being updated, and could come from some other location, such as a collection of templates:
<xf:insert nodeset="list/y" origin="templates/x" />
The result would be:
<list>
<y>y1</y>
<y>y2</y>
<y>y3</y>
<x>x1</x>
</list>
If the nodeset referred to is empty then the node being copied is created as a child of the insert handler's context node (if you are not clear on the evaluation context then read this):
<xf:group ref="list">
<xf:repeat nodeset="y">
<xf:output ref="." />
</xf:repeat>
<xf:trigger>
<xf:label>Add new 'x'</xf:label>
<xf:action ev:event="DOMActivate">
<!--
The evaluation context here is still 'list', from
the xf:group, above.
-->
<xf:insert nodeset="y" origin="../templates/x" />
</xf:action>
</xf:trigger>
</xf:group>
In many situations there may be no natural 'context', such as the group in the previous example. In these circumstances we use the context attribute to set a context explicitly:
<xf:insert context="list" nodeset="y" origin="../templates/x" />
Note that the @origin value is also evaluated relative to the evaluation context.