Search code examples
xmlformsorbeon

Orbeon forms generates duplicate tags


I'm trying to create a form in orbeon forms (4.10 PE) with a repeated grid. I would like to fill this form using a request parameter. However, it seems that when I use xf:insert to replace the main data instance, the xml is somehow transformed.

I have the following minimal form published as test/test at http://localhost:8080/orbeon/fr/test/test :

<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:ev="http://www.w3.org/2001/xml-events"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
     xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
     xmlns:exf="http://www.exforms.org/exf/1-0"
     xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
     xmlns:saxon="http://saxon.sf.net/"
     xmlns:sql="http://orbeon.org/oxf/xml/sql"
     xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:fb="http://orbeon.org/oxf/xml/form-builder">;
<xh:head>
    <xh:title>Untitled Form</xh:title>
    <xf:model id="fr-form-model" xxf:expose-xpath-types="true">

        <!-- Main instance -->
        <xf:instance id="fr-form-instance" xxf:exclude-result-prefixes="#all">
            <form>
                <section-1>
                    <control-1/>
                    <mygrid>
                        <mygrid-iteration>
                            <control-5/>
                            <control-6/>
                        </mygrid-iteration>
                        <mygrid-iteration>
                            <control-5/>
                            <control-6/>
                        </mygrid-iteration>
                    </mygrid>
                </section-1>
            </form>
        </xf:instance>

        <!-- Bindings -->
        <xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
            <xf:bind id="section-1-bind" name="section-1" ref="section-1">
                <xf:bind id="control-1-bind" name="control-1" ref="control-1"/>
                <xf:bind id="mygrid-bind" ref="mygrid" name="mygrid">
                    <xf:bind id="mygrid-iteration-bind" ref="mygrid-iteration" name="mygrid-iteration">
                        <xf:bind id="control-5-bind" ref="control-5" name="control-5"/>
                        <xf:bind id="control-6-bind" ref="control-6" name="control-6"/>
                    </xf:bind>
                </xf:bind>
            </xf:bind>
        </xf:bind>

        <!-- Metadata -->
        <xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
            <metadata>
                <application-name>test</application-name>
                <form-name>test</form-name>
                <title xml:lang="en">Untitled Form</title>
                <description xml:lang="en"/>
                <singleton>false</singleton>
            </metadata>
        </xf:instance>

        <!-- Attachments -->
        <xf:instance id="fr-form-attachments" xxf:exclude-result-prefixes="#all">
            <attachments>
                <css mediatype="text/css" filename="" size=""/>
                <pdf mediatype="application/pdf" filename="" size=""/>
            </attachments>
        </xf:instance>

        <!-- All form resources -->
        <!-- Don't make readonly by default in case a service modifies the resources -->
        <xf:instance id="fr-form-resources" xxf:readonly="false" xxf:exclude-result-prefixes="#all">
            <resources>
                <resource xml:lang="en">
                    <control-5>
                        <label/>
                        <hint/>
                    </control-5>
                    <control-6>
                        <label/>
                        <hint/>
                    </control-6>
                    <section-1>
                        <label>Untitled Section</label>
                    </section-1>
                    <control-1>
                        <label/>
                        <hint/>
                        <alert/>
                    </control-1>
                </resource>
            </resources>
        </xf:instance>

        <!-- Utility instances for services -->
        <xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
            <request/>
        </xf:instance>

        <xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
            <response/>
        </xf:instance>
        <xf:instance xxf:readonly="true" xxf:exclude-result-prefixes="#all" id="mygrid-template">
            <mygrid-iteration t="3">
                <control-5/>
                <control-6/>
            </mygrid-iteration>
        </xf:instance>
        <xf:insert ev:event="xforms-model-construct-done" ref="instance('fr-form-instance')" 
                   origin="xxf:get-request-attribute('fr-form-data')"/>
    </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">;
            <fr:section id="section-1-control" bind="section-1-bind">
                <xf:label ref="$form-resources/section-1/label"/>
                <fr:grid>
                    <xh:tr>
                        <xh:td>
                            <xf:input id="control-1-control" bind="control-1-bind">
                                <xf:label ref="$form-resources/control-1/label"/>
                                <xf:hint ref="$form-resources/control-1/hint"/>
                                <xf:alert ref="$fr-resources/detail/labels/alert"/>
                            </xf:input>
                        </xh:td>
                        <xh:td/>
                    </xh:tr>
                </fr:grid>
                <fr:grid id="mygrid-control" bind="mygrid-bind" repeat="content" min="1"
                         template="instance('mygrid-template')">
                    <xh:tr>
                        <xh:td>
                            <xf:input id="control-5-control" bind="control-5-bind">
                                <xf:label ref="$form-resources/control-5/label"/>
                                <xf:hint ref="$form-resources/control-5/hint"/>

                                <xf:alert ref="$fr-resources/detail/labels/alert"/>
                            </xf:input>
                        </xh:td>
                    </xh:tr>
                    <xh:tr>
                        <xh:td>
                            <xf:input id="control-6-control" bind="control-6-bind">
                                <xf:label ref="$form-resources/control-6/label"/>
                                <xf:hint ref="$form-resources/control-6/hint"/>
                                <xf:alert ref="$fr-resources/detail/labels/alert"/>
                            </xf:input>
                        </xh:td>
                    </xh:tr>
                </fr:grid>
            </fr:section>
        </fr:body>
    </fr:view>
</xh:body>

I then take the contents of the 'fr-form-instance' instance and base64 encode the xml. Then I post the xml using a simple html form:

<html>
<head>
</head>
<body>
<form method="post" action="http://localhost:8080/orbeon/fr/test/test/new">
<input type="hidden" name="fr-form-data" value="PGZvcm0+DQogICAgICAgICAgICAgICAgICAgIDxzZWN0aW9uLTE+DQogICAgICAgICAgICAgICAgICAgICAgICA8Y29udHJvbC0xLz4NCiAgICAgICAgICAgICAgICAgICAgICAgIDxteWdyaWQ+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgPG15Z3JpZC1pdGVyYXRpb24+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxjb250cm9sLTU+dmlqZjwvY29udHJvbC01Pg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8Y29udHJvbC02PnplczwvY29udHJvbC02Pg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbXlncmlkLWl0ZXJhdGlvbj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bXlncmlkLWl0ZXJhdGlvbj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvbnRyb2wtNS8+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxjb250cm9sLTYvPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbXlncmlkLWl0ZXJhdGlvbj4NCiAgICAgICAgICAgICAgICAgICAgICAgIDwvbXlncmlkPg0KICAgICAgICAgICAgICAgICAgICA8L3NlY3Rpb24tMT4NCiAgICAgICAgICAgICAgICA8L2Zvcm0+"/>
<input type="submit" value="submit" />
</form>
</body>
</html>

When I look at the 'fr-form-instance' instance in the Orbeon Forms XForms Inspector I see that there is an extra 'mygrid-iteration' iteration tag and the controls are not rendered. Below is the xml as shown in the Forms Inspector:

<form>
    <section-1>
        <control-1/>
        <mygrid>
            <mygrid-iteration>
                <mygrid-iteration>
                    <control-5>vijf</control-5>
                    <control-6>zes</control-6>
                </mygrid-iteration>
                <mygrid-iteration>
                    <control-5/>
                    <control-6/>
                </mygrid-iteration>
            </mygrid-iteration>
        </mygrid>
    </section-1>
</form>

Notice the extra mygrid-iteration.

Am I doing anything wrong? Is this a bug in Orbeon ? If so, is there a known work-around?


Solution

  • Pre-4.8, Orbeon Forms didn't have an "iteration" element in the XML. You just had <mygrid>, and that element itself was repeated. Then 4.8 introduced an iteration element, but, for backward compatibility, that iteration element is removed when saving data to the database or sending data, and added when loading data from the database, or receiving the data through a POST.

    In this last case, if you'd like to have that iteration element, then add the data-format-version=edge to your request, and Orbeon Forms won't try to add the iteration element.