我在更新包含重复节点的实例结构时遇到了问题。我想使用<action while=""/>
构造,但在此循环中使用已定义的迭代器时出现问题。最终它总是使用一个值(第一个),即使它是递增的。我使用xxforms:evaluate
函数解决了这个问题,因此我有:
xxforms:evaluate(concat('instance(''main'')/item[',xxforms:bind('idx'),']'))
而不是更简单
instance('main')/item[xxforms:bind('idx')]
这是迭代操作中节点列表的唯一方法吗?
示例:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xxforms="http://orbeon.org/oxf/xml/xforms">
<head>
<title>Test</title>
<xf:model id="model">
<xf:instance id="main" xmlns="">
<main>
<item>
<name />
</item>
<item>
<name />
</item>
<item>
<name />
</item>
</main>
</xf:instance>
<xf:instance id="temp" xmlns="">
<main>
<idx></idx>
<value>inserted node</value>
</main>
</xf:instance>
<xf:bind id="idx" nodeset="instance('temp')/idx" type="xsd:integer" />
</xf:model>
</head>
<body>
<xf:trigger>
<xf:label>Not working as expected</xf:label>
<xf:action ev:event="DOMActivate">
<xf:setvalue bind="idx" value="1" />
<xf:action while="number(xxforms:bind('idx')) le count(instance('main')/item)">
<xf:insert context="instance('main')/item[xxforms:bind('idx')]" nodeset="name" position="after" origin="instance('temp')/value" if="not(exists(value))" />
<xf:setvalue bind="idx" value=". + 1" />
</xf:action>
</xf:action>
</xf:trigger>
<xf:trigger>
<xf:label>Working as expected but too complicated</xf:label>
<xf:action ev:event="DOMActivate">
<xf:setvalue bind="idx" value="1" />
<xf:action while="number(xxforms:bind('idx')) le count(instance('main')/item)">
<xf:insert context="xxforms:evaluate(concat('instance(''main'')/item[',xxforms:bind('idx'),']'))" nodeset="name" position="after" origin="instance('temp')/value" if="not(exists(value))" />
<xf:setvalue bind="idx" value=". + 1" />
</xf:action>
</xf:action>
</xf:trigger>
<widget:xforms-instance-inspector id="orbeon-xforms-inspector" xmlns:widget="http://orbeon.org/oxf/xml/widget" />
</body>
</html>
所以我得到了结果(第一次触发):
<main>
<item>
<name/>
<value>inserted node</value>
</item>
<item>
<name/>
</item>
<item>
<name/>
</item>
</main>
但预期(第二次触发):
<main>
<item>
<name/>
<value>inserted node</value>
</item>
<item>
<name/>
<value>inserted node</value>
</item>
<item>
<name/>
<value>inserted node</value>
</item>
</main>
答案 0 :(得分:1)
这是一个有效的版本:
<xf:action ev:event="DOMActivate">
<xf:setvalue bind="idx" value="1"/>
<xf:action while="xs:integer(xxforms:bind('idx')) le count(instance('main')/item)">
<xf:insert context="instance('main')/item[xs:integer(xxforms:bind('idx'))]" nodeset="name" position="after"
origin="instance('temp')/value" if="not(exists(value))"/>
<xf:setvalue bind="idx" value=". + 1"/>
</xf:action>
</xf:action>
问题是xxforms:bind('idx')
会返回无类型值,即使您指定了xsd:integer
也是如此。 XForms目前没有指定绑定上的类型注释必须提供类型值(请参阅这些notes on type annotation)。这意味着在这种情况下,谓词值不是数字(XPath同时具有布尔值和数字谓词,这通常是混淆的来源)。为了使它成为数字谓词,需要转换为数字。
此处我使用xs:integer
,因为number
是一种XPath 1遗留函数,它返回xs:double
,而count()
函数返回xs:integer
)。
xxforms:iterate
有更简单的解决方案:
<xf:action ev:event="DOMActivate" xxforms:iterate="item">
<xf:insert if="not(exists(value))"
context="."
nodeset="name"
origin="instance('temp')/value"/>
</xf:action>
iterate
目前是一个扩展程序,但是XForms 2 will add it.