XSLTForms中重复组内元素上下移动功能异常问题求助
解决XSLTForms中跨重复组的元素移动问题
用XSLTForms渲染XForms表单时,把同一可重复父元素<msIdentifier>下的元素分成两个重复组展示(满足UI需求):第一组是country/settlement/institution,第二组是altIdentifier/msName。目前第一组元素能正常在组内上下移动,但第二组完全无法实现移动功能。核心问题是repeat的index只作用于当前分组后的重复组,没法拿到元素在整个父元素里的真实位置,导致移动逻辑里的节点定位完全错误。
可行解决思路
- 放弃依赖repeat index,计算元素绝对位置:用
count(preceding-sibling::*) + 1替代index('xxx'),直接获取当前元素在父节点所有子元素中的真实位置,不受分组影响。 - 统一基于父元素全量子节点操作:insert和delete操作时,直接定位到父元素的所有子节点集合,用绝对位置确定插入点和删除节点,避免分组repeat的索引干扰。
- 简化上下文引用:利用XForms的上下文特性,用
..直接指代当前元素的父节点<msIdentifier>,不用额外的repeatIndex实例定位父元素,减少冗余。
修改后的完整代码
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:tei="http://www.tei-c.org/ns/1.0"> <head> <xf:model id="m-mss"> <xf:instance id="i-rec"> <TEI xmlns="http://www.tei-c.org/ns/1.0"> <msIdentifier> <!-- group a --> <country>1a</country> <institution>2a</institution> <settlement>3a</settlement> <institution>4a</institution> <!-- group b --> <altIdentifier>1b</altIdentifier> <altIdentifier>2b</altIdentifier> <altIdentifier>3b</altIdentifier> <msName>4b</msName> </msIdentifier> </TEI> </xf:instance> <xf:instance id="i-move"> <data xmlns=""> <tmp/> </data> </xf:instance> </xf:model> </head> <body> <h2>Parent Element </h2> <xf:repeat ref="instance('i-rec')//tei:msIdentifier" id="msIdentifierRepeatLevel1"> <div id="elementGroup" style="margin:12px; padding:12px; border:1px solid #ccc;"> <div> <h2>location, institution, settlement</h2> <div> <xf:repeat id="msIdentifierRepeatLevel11" ref="./*[contains(local-name(),'country') or contains(local-name(),'settlement') or contains(local-name(),'institution')]"> <div class="btn-group" role="group"> <xf:trigger appearance="minimal" class="btn controls moveUp inline"> <xf:label>up</xf:label> <xf:action ev:event="DOMActivate"> <!-- 获取当前元素在父节点中的绝对位置 --> <setvalue ref="instance('i-move')/tmp" value="count(preceding-sibling::*) + 1"/> <xf:if test="instance('i-move')/tmp > 1"> <insert origin="." nodeset="../*" at="instance('i-move')/tmp - 1" position="before"/> <delete nodeset="../*[instance('i-move')/tmp + 1]"/> </xf:if> </xf:action> </xf:trigger> | <xf:trigger appearance="minimal" class="btn controls moveDown inline"> <xf:label>down</xf:label> <xf:action ev:event="DOMActivate"> <setvalue ref="instance('i-move')/tmp" value="count(preceding-sibling::*) + 1"/> <xf:if test="instance('i-move')/tmp < count(../*)"> <insert origin="." nodeset="../*" at="instance('i-move')/tmp + 1" position="after"/> <delete nodeset="."/> </xf:if> </xf:action> </xf:trigger> | <span class="elementLabel"><xf:output value="local-name()" class="elementLabel"/></span> </div> <span class="element"> <xf:input class="elementInput" ref="."/> </span> </xf:repeat> </div> </div> </div> <div id="elementGroup2" style="margin:12px; padding:12px; border:1px solid #ccc;"> <div> <h2>altIdentifier, msName</h2> <div> <xf:repeat id="msIdentifierRepeatLevel12" ref="./*[contains(local-name(),'altIdentifier') or contains(local-name(),'msName')]"> <div class="btn-group" role="group"> <xf:trigger appearance="minimal" class="btn controls moveUp inline"> <xf:label>up</xf:label> <xf:action ev:event="DOMActivate"> <setvalue ref="instance('i-move')/tmp" value="count(preceding-sibling::*) + 1"/> <xf:if test="instance('i-move')/tmp > 1"> <insert origin="." nodeset="../*" at="instance('i-move')/tmp - 1" position="before"/> <delete nodeset="../*[instance('i-move')/tmp + 1]"/> </xf:if> </xf:action> </xf:trigger> | <xf:trigger appearance="minimal" class="btn controls moveDown inline"> <xf:label>down</xf:label> <xf:action ev:event="DOMActivate"> <setvalue ref="instance('i-move')/tmp" value="count(preceding-sibling::*) + 1"/> <xf:if test="instance('i-move')/tmp < count(../*)"> <insert origin="." nodeset="../*" at="instance('i-move')/tmp + 1" position="after"/> <delete nodeset="."/> </xf:if> </xf:action> </xf:trigger> | <span class="elementLabel"><xf:output value="local-name()" class="elementLabel"/></span> </div> <span class="element"> <xf:input class="elementInput" ref="."/> </span> </xf:repeat> </div> </div> </div> </xf:repeat> </body> </html>
关键修改点说明
- 添加tei命名空间:在根元素声明
xmlns:tei="http://www.tei-c.org/ns/1.0",避免节点定位时的命名空间问题。 - 替换位置计算方式:用
count(preceding-sibling::*) + 1获取元素在父节点的真实位置,替代原有的index('xxx')。 - 简化父节点引用:用
../*直接指代<msIdentifier>下的所有子元素,不用通过repeatIndex实例定位。 - 添加边界判断:用
<xf:if>限制移动操作仅在元素不在边界时执行,避免无效操作。
内容的提问来源于stack exchange,提问作者wsalesky
相关产品推荐
相关产品推荐

