XSLTForms/setnode
xf:setnode
操作是 XForms 的一个实验性扩展,有助于使用 XSLT 转换的输出(见transform() 函数)或混合内容编辑器的输出(见使用 TinyMCE 作为 XForms 控件 的讨论)来更新实例文档。
此操作使用 xf:setnode
元素来指示。它有三个关键属性
ref
属性是一个单节点绑定属性,它指示目标节点。inner
属性指定应替换目标节点子节点的节点;其值为节点的序列化 XML 形式。outer
属性指定应替换目标节点的节点;其值为替换节点的序列化 XML 形式。
inner
和 outer
属性是互斥的;必须指定其中一个,但不能同时指定两者。正如在属性值中表示序列化 XML 时通常的做法一样,序列化形式中的左尖括号和与号必须进行转义。
inner
或 outer
属性的值将被解析为 XML,以生成 DOM 节点,并且生成的节点将替换目标节点的子节点或目标节点本身。
以下示例显示了一个触发器,它将名为 input
的实例替换为一个新文档。
<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>
setnode
的一个更常见的用法可能是使用 XSLT 样式表或混合内容编辑器来更新实例,它们都返回包含其结果的序列化 XML 形式的字符串。
假设我们有一个输入实例,用户可以通过表单修改它,以及一个 XSLT 样式表 (make-svg.xsl
),它可以处理输入实例并创建一个表示实例中某些信息的 SVG 图表。为了允许用户生成一个新的图表,我们可以提供一个触发器,指定如下
<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>
这假设我们有一个名为 svg
的实例,转换的输出应放在那里。它还假设在某处有一个开关语句,其中包含一个名为 picture
的情况,它显示生成的 SVG。
在标准 XForms 1.1 中,实现类似效果的一种方法是将字符串(序列化 XML)提交到一个服务器,该服务器以 application/xml
(或类似的)MIME 类型将其反射回来,并指定提交更新所讨论的实例。
上面给出的示例将被改写为
<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
提交将 svg
实例的字符串值提交到服务器,服务器将其反射回 XML(因此浏览器将其解析并按常规更新实例)
<xf:submission id="parse-as-xml"
ref="instance('svg')/text()"
method="post"
resource="../lib/reflect-as-xml.sh"
replace="instance"
instance="svg"
/>
服务器上的 CGI 脚本除了返回提交的数据以外什么也不做,并将数据标记为 XML
#!/bin/sh
echo "Content-Type: application/xml"
echo
cat
为了在 XForms 2.0 中实现类似效果,可以使用 xf:insert
操作,在 origin
属性的值中使用 XForms 2.0 的 parse()
函数。
[需要示例。]