Search code examples
orbeonxformsxsltformsxforms-betterform

How to do an xforms:insert without the need of xforms:delete at the end?


<xf:action ev:event="xforms-model-construct">
    <xf:insert nodeset="instance('subInstance')/type" origin="instance('defaultType')/type"/>
</xf:action>

I want to populate an instance based on another one. I can do this using xf:insert as shown above.

However, I realised that the instance 'subInstance' must contain an empty type element before starting the xf:inserts.

<subInstance>
  <type/>
</subInstance>

So after all the xf:inserts, I need do the following to delete the first empty one:

<xf:delete nodeset="instance('subInstance')/type" at="1" />

Is there something wrong with this method or is there a way I can insert directly without an initial empty ?


Solution

  • Two answers:

    You don't really need an initial type element

    Your original instance can simply be:

    <subInstance/>
    

    And then you can insert into the subInstance element with:

    <xf:action ev:event="xforms-model-construct">
        <xf:insert
            context="instance('subInstance')"
            origin="instance('defaultType')/type""/>
    </xf:action>
    

    Using context without nodeset or ref says that you want to insert into the node pointed to by context.

    You can still do what you want but with XForms 2.0 support

    If you want to keep the original nested type element, you could write this:

    <xf:action ev:event="xforms-model-construct">
        <xf:insert
            nodeset="instance('subInstance')"
            origin="
                xf:element(
                    'subInstance',
                    instance('defaultType')/type
                )
            "/>
    </xf:action>
    
    1. By targeting the root element of the destination instance, the entire instance will be replaced. This is already the case with XForms 1.1.
    2. With the origin attribute's use of the xf:element() function from XForms 2.0, you can dynamically create an XML document rooted at subInstance and containing only the type elements from the defaultType instance.

    To make this even more modern, you would replace nodeset with ref, as nodeset is deprecated in XForms 2.0:

    <xf:action ev:event="xforms-model-construct">
        <xf:insert
            ref="instance('subInstance')"
            origin="
                xf:element(
                    'subInstance',
                    instance('defaultType')/type
                )
            "/>
    </xf:action>