在可重复部分中定义元素时是否可以使用绝对XPath?

时间:2014-12-04 10:59:05

标签: orbeon xforms

我有一个使用可重复部分的表单。这在使用表单节点的相对路径时工作正常。问题是我不想强制在表单的节点中使用唯一的名称。一个例子:

<form>
  <section-personalData>
    <age/>
  </section-personalData>
  <section-kids-personalData>
     <section-kids-personalData-iterator>
       <age/>
     </section-kids-personalData-iterator>
  </section-kids-personalData>
</form>

在此示例中,由于元素<age>处于不同的级别,因此允许具有相同的名称。当然,为了允许它,在定义节点的<bind>部分时,我需要指定节点的完整路径以避免混淆。

<xf:bind id="age-bind" name="age" ref="/form/section-personalData/age" required="true()"/>

这是正常的。问题在于可重复部分内部的元素。

<xf:bind id="age-1-bind" name="age-1" ref="/form/section-kids-personalData/section-kids-personalData-iterator/age" required="true()"/>

这几乎可以工作,但我发现了一个意想不到的行为。当您有多个迭代并回答age值时,所有迭代总是具有相同的答案(当您更改其中一个时,ALL将被更改)。我用输入字段,单选按钮,......进行了实验。

使用Orbeon Builder时,所有元素必须具有唯一名称。但是由于客户端的限制,我们感兴趣的是在两个元素中都有相同的名称。

我复制了一个可以在Orbeon中执行的完整示例来测试问题。

<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
         xmlns:ev="http://www.w3.org/2001/xml-events"
         xmlns:exf="http://www.exforms.org/exf/1-0"
         xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
         xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
         xmlns:saxon="http://saxon.sf.net/"
         xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
         xmlns:sql="http://orbeon.org/oxf/xml/sql"
         xmlns:xf="http://www.w3.org/2002/xforms"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:xs="http://www.w3.org/2001/XMLSchema"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
         xmlns:xxi="http://orbeon.org/oxf/xml/xinclude">
    <xh:head>
        <xh:meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
        <xh:title>Loop</xh:title>
        <xf:model id="fr-form-model" xxf:expose-xpath-types="true">
            <xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
                <metadata>
                    <application-name>WebForms</application-name>
                    <form-name>Loop_v1</form-name>
                    <title xml:lang="en">Loop</title>
                    <description xml:lang="en">Version: 1. Modification date: 2014-12-04 10:06:03. Publication date: 2014-12-04 10:52:43.</description>
                </metadata>
            </xf:instance>
            <xf:instance id="fr-form-instance">
                <form>
                    <Category1>
                        <Loop>
                            <Loop-iterator>
                                <Question/>
                            </Loop-iterator>
                         </Loop>
                    </Category1>
                </form>
            </xf:instance>
            <xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
                <xf:bind id="Category1-bind" name="Category1" ref="/form/Category1">
                    <xf:bind id="Loop-bind" name="Loop" ref="/form/Category1/Loop">
                        <xf:bind id="Loop-iterator-bind" name="Loop-iterator"
                                 ref="/form/Category1/Loop/Loop-iterator">
                                     <xf:bind id="Question-bind" name="Question"
                                     ref="/form/Category1/Loop/Loop-iterator/Question"
                                     required="true()"/>
                        </xf:bind>
                    </xf:bind>
                </xf:bind> 
            </xf:bind>
            <xf:instance id="fr-form-attachments">
                <attachments>
                    <css filename="" mediatype="text/css" size=""/>
                    <pdf filename="" mediatype="application/pdf" size=""/>
                </attachments>
            </xf:instance>
            <xf:instance id="fr-form-resources" xxf:readonly="false">
                <resources>
                    <resource xml:lang="en">
                        <Category1>
                            <label>Category1</label>
                            <hint/>
                            <alert/>
                            <Loop>
                                <label>Loop</label>
                                <hint/>
                                <alert/>
                                <Question>
                                    <label>Question</label>
                                    <hint/>
                                    <alert/>
                                    <item>
                                        <label>Answer</label>
                                        <hint/>
                                        <value>Answer</value>
                                    </item>
                                    <item>
                                        <label>Answer2</label>
                                        <hint/>
                                        <value>Answer2</value>
                                    </item>
                                    <item>
                                        <label>Answer3</label>
                                        <hint/>
                                        <value>Answer3</value>
                                    </item>
                                </Question>
                            </Loop>
                        </Category1>
                    </resource>
                </resources>
            </xf:instance>
            <xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
                <response/>
            </xf:instance>
            <xf:instance xxf:readonly="true" id="Loop-template">
                <Loop-iterator>
                    <Question/>
                </Loop-iterator>
            </xf:instance>
        </xf:model>
    </xh:head>
    <xh:body>
        <fr:view>
            <fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
                     xmlns:oxf="http://www.orbeon.com/oxf/processors"
                     xmlns:p="http://www.orbeon.com/oxf/pipeline"
                     xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel">               
                <fr:section bind="Category1-bind" id="Category1-control">
                    <xf:label mediatype="text/html" ref="$form-resources/Category1/label"/>
                    <xf:hint ref="$form-resources/Category1/hint"/>
                    <xf:alert ref="$form-resources/Category1/alert"/>
                    <fr:section bind="Loop-bind" id="Loop-control" max="100" min="1" repeat="true"
                                template="instance('Loop-template')">
                        <xf:label mediatype="text/html" ref="$form-resources/Category1/Loop/label"/>
                        <xf:hint ref="$form-resources/Category1/Loop/hint"/>
                        <xf:alert ref="$form-resources/Category1/Loop/alert"/>
                        <xh:tr>
                            <xh:td>
                                <xf:select1 appearance="full" bind="Question-bind" id="Question-control">
                                    <xf:label mediatype="text/html" ref="$form-resources/Category1/Loop/Question/label"/>
                                    <xf:hint ref="$form-resources/Category1/Loop/Question/hint"/>
                                    <xf:alert ref="$form-resources/Category1/Loop/Question/alert"/>
                                    <xf:itemset ref="$form-resources/Category1/Loop/Question/item">
                                        <xf:label ref="label"/>
                                        <xf:value ref="value"/>
                                        <xf:hint ref="hint"/>
                                    </xf:itemset>
                                </xf:select1>
                            </xh:td>
                        </xh:tr>
                    </fr:section>
                </fr:section>
            </fr:body>
        </fr:view>
    </xh:body>
</xh:html>

在此示例中,对于Question的任何重复值,不可能有不同的值。

我真的需要为两个节点使用相同的名称,然后我认为使用完整的xpath是解决方案。因此问题是:我如何使用完整路径来处理可重复部分内的元素?对于任何其他情况,完整的xpath正常工作。 (此刻我正在使用Orbeon 4.7)。

1 个答案:

答案 0 :(得分:1)

我首先应该说,在多个地方更改数据格式以支持相同的名称是一个麻烦。如果你这样做,在表单生成器中中断,因为它目前是一个强有力的假设。 可能在Form Runner中也会中断。

这就是说,对于重复,你来使用相对的XPath表达式。我没有看到解决方法。所以而不是:

<xf:bind id="Category1-bind" name="Category1" ref="/form/Category1">
    <xf:bind id="Loop-bind" name="Loop" ref="/form/Category1/Loop">
        <xf:bind id="Loop-iterator-bind" name="Loop-iterator"
                 ref="/form/Category1/Loop/Loop-iterator">
                     <xf:bind id="Question-bind" name="Question"
                     ref="/form/Category1/Loop/Loop-iterator/Question"
                     required="true()"/>
        </xf:bind>
    </xf:bind>
</xf:bind>

使用:

<xf:bind id="Category1-bind" name="Category1" ref="Category1">
    <xf:bind id="Loop-bind" name="Loop" ref="Loop">
        <xf:bind id="Loop-iterator-bind" name="Loop-iterator"
                 ref="Loop-iterator">
                     <xf:bind id="Question-bind" name="Question"
                     ref="Question"
                     required="true()"/>
        </xf:bind>
    </xf:bind>
</xf:bind>

它没有遵循这一点,通过在不同的地方使用相同的名称,您需要使用绝对路径。绑定可以用变量来引用,也可以是相对的。你应该有这样的层次结构:

<xf:bind id="section-personalData-bind" name="section-personalData">
    <xf:bind id="age-bind" name="age" ref="age" required="true()"/>
</xf:bind>

<xf:bind id="section-kids-personalData-bind" name="section-kids-personalData">
    <xf:bind id="section-kids-personalData-iteration-bind" name="section-kids-personalData-iterator">
        <xf:bind id="age-1-bind" name="age-1" ref="age" required="true()"/>
    </xf:bind>
</xf:bind>

参考$age会找到第一个,提到$age-1第二个。