xf:setnode action is an experimental extension of XForms, helpful for updating an instance document with the output of an XSLT transformation (see the transform() function) or with the output of a mixed-content editor (see the discussion of using TinyMCE as an XForms control).
The action is indicated using the
xf:setnode element. It has three crucial attributes:
refattribute is a single-node binding attribute which indicates the target node.
innerattribute specifies the node(s) which should replace the children of the target node; its value is the serialized XML form of the nodes.
outerattribute specifies the node which should replace the target node; its value is the serialized XML form of the replacement node.
outer attributes are mutually exclusive; one or the other must be specified, but not both. As is usual when representing serialized XML within an attribute value, the left angle brackets and ampersands in the serialized form must be escaped.
The value of the
outer attribute is parsed as XML to produce DOM nodes, and the resulting nodes replace either the children of the garget node, or the target node itself.
The following example shows a trigger which replaces an instance named
input with a new document.
<xf:trigger> <xf:label>Generate diagram</xf:label> <xf:action ev:event="DOMActivate"> <xf:setnode ref="instance('input')" outer="<doc> <title>My document</title> <chapter> <p>Hello, world!</p> </chapter> </doc>"/> </xf:action> </xf:trigger>
A perhaps more common usage of
setnode is to update an instance with the result of running an XSLT stylesheet or a mixed-content editor, both of which return strings with the serialized-XML form of their result.
Suppose we have an input instance which the user can modify through the form, and an XSLT stylesheet (
make-svg.xsl) which can process the input instance and create an SVG diagram representing some information from the instance. To allow the user to generate a fresh diagram, we could supply a trigger specified as follows:
<xf:trigger> <xf:label>Generate diagram</xf:label> <xf:action ev:event="DOMActivate"> <xf:setnode ref="instance('svg')" outer="transform(instance('input'),'make-svg.xsl')"/> <xf:toggle case="picture"/> </xf:action> </xf:trigger>
This assumes that we have an instance named
svg, where the output of the transformation should go. It also assumes that there is a switch statement somewhere with a case named
picture, which displays the generated SVG.
Achieving similar effects in standard XForms 1.1
In standard XForms 1.1, one way to achieve similar effects is to submit the string (the serialized XML) to a server which reflects it back unchanged, with the MIME type
application/xml (or similar), and specify that the submission updates the instance in question.
The example given above would be rewritten as:
<xf:trigger> <xf:label>Generate diagram</xf:label> <xf:action ev:event="DOMActivate"> <xf:setvalue ref="instance('svg')" value="transform(instance('input'),'make-svg.xsl')"/> <xf:send submission="parse-as-xml"/> <xf:toggle case="picture"/> </xf:action> </xf:trigger>
parse-as-xml submission submits the string value of the
svg instance to the server, which reflects it back as XML (so the browser parses it and updates the instance normally):
<xf:submission id="parse-as-xml" ref="instance('svg')/text()" method="post" resource="../lib/reflect-as-xml.sh" replace="instance" instance="svg" />
The CGI script on the server does nothing but return the submitted data, labeled as XML:
#!/bin/sh echo "Content-Type: application/xml" echo cat
Achieving similar effects in standard XForms 2.0
To achieve similar effects in XForms 2.0, one can use the
xf:insert action, using the XForms 2.0
parse() function in the value of the