Orbeon - dynamic XML in POST request body - orbeon

I need help with body of POST request. I need send XML whitch can be dynamically assemble. Not only putting values in elements.
I work with Orbeon 2021.1.2 PE. There are two cases I came across when connecting to my backend and they are quite similar:
1] There is a array in the request where its length is based on the data in the form.
When using a request template:
<SendAction>
<IDs>
<ID></ID>
</IDs>
</SendAction>
You can simply put a value using //ID and the result is this:
<SendAction>
<IDs>
<ID>AAA</ID>
</IDs>
</SendAction>
But I would need a request when the number of <ID> is N like:
<SendAction>
<IDs>
<ID>AAA</ID>
<ID>BBB</ID>
<ID>CCC</ID>
</IDs>
</SendAction>
2] The request again has a dynamically long array but I need put entire object. E.g:
<Wheapons>
<Weapon>
<LicenseNumber>123456789</LicenseNumber>
<Name>Gun A</KindOfWeapon>
<Category>0</Category>
</Weapon>
<Weapon>
<LicenseNumber>987654321</LicenseNumber>
<Name>Gun B</KindOfWeapon>
<Category>0</Category>
</Weapon>
<Wheapons>
I hope you get my point. Data in second example I have in fr:dataset() and in Repeated Grid too (it is output of diferent endpoint). I tried to insert whole blocks of XML, but Orbeon always encode the characters in xml ('<' to "& lt;" and '>' to "& gt;") and therefore the request is not processed. This behavior is basically good, because I'm trying something like XML injection. But I achieve the same bad result when using the xf:element() function. Is this problem solvable by some funcitons or I'm complete wrong? Thank you!

My understanding is that your form has a repeated grid, and that you would like to call a service POSTing XML to that service based on the values of fields inside a repeated grid. This isn't something that you can do with the Services & Actions in Form Builder; currently, those only let you send individual values to a service. So, instead, you'll need to write that logic in XForms. At a high level:
The XForms will go in a custom model (doc), i.e. a separate file on the server with your XForms logic.
In that XForms, you write an event handler, for an event of your choosing, and you will dispatch that event from a process, in your properties-local.xml, with xf:dispatch() (doc).
Your XForms custom model also declares an xf:submission, to do the actual POST, an instance, with the data to be posted, and in the event handler you populate the instance from the data in your grid, and run the submission.

I find simple and dummy solution but #avernet was right. If you want generic function for whole project you must write own custom model.
Here is my snippet:
<xf:instance id="test_service-template">
<item>
<id/>
</item>
</xf:instance>
<xf:instance id="test_service-instance">
<values>
<item>
<id>123</id>
</item>
</values>
</xf:instance>
<xf:instance id="test_service-resposne-service-instance">
<response/>
</xf:instance>
<xf:submission id="test_service-submission" resource="/fr/service/custom/orbeon/echo"
ref="instance('test_service-instance')"
method="post"
serialization="application/xml"
mediatype="application/xml"
replace="instance"
instance="test_service-resposne-service-instance"/>
<xf:action id="test_action-binding">
<xf:action event="DOMActivate" ev:observer="control-2-control" if="true()">
<xf:insert context="xxf:instance('test_service-instance')" ref="values"
origin="xxf:instance('test_service-template')"/>
<xf:setvalue ref="xxf:instance('test_service-instance')/values/item[1]/id" value="'321'"/>
<xf:send submission="test_service-submission"/>
</xf:action>
</xf:action>
If you don't use Services & Actions in Form Builder you can send your own instance as body of request (test_service-instance).
Before submission you can simple build this instance (by insert and setvalue). You can put then somewhere else in form (for example under trigger). Response of submission can have own instance too.

Related

Orbeon: Constraints on UI Parent Elements

Does Orbeon have a way to provide validation on parents of UI elements? I've been testing it with some files from previous work on a different XForm engine, and I've noticed a difference in the handling of the errors on fields without direct UI inputs.
My instance looks like:
<set>
<value prop="1"/>
<value prop="2"/>
<value prop="3"/>
</set>
My UI section looks like:
<xf:group ref="set">
<h2>set</h2>
<xf:alert>Bigger Error</xf:alert>
<xf:repeat ref="value">
<xf:input ref=".">
<xf:label>Value</xf:label>
<xf:alert>Error</xf:alert>
</xf:input>
</xf:repeat>
</xf:group>
In the other engine, if a constraint such as <xf:bind ref="set" constraint="count(value) gt 3"/> failed, the error in the set group would show up in the UI. Is there a way for Orbeon to have this same behavior, or is that a non-standard implementation that I was unknowingly relying on?
In the case of Orbeon Forms, if you have an xf:group bound to an invalid node, just as for leaf controls, by default, you'll see the red icon with an exclamation point in the UI if you have <xf:alert> for the group.
If you don't have an <xf:alert>, the HTML element corresponding to the group will just have the xforms-invalid class in the DOM, which allows you, with CSS, to style the group in a way appropriate for your use case.

Trigger Javascript, Java, or a Bash Script on submit in Orbeon?

I would like to know if it is possible to trigger either a Java servlet, Javascript or a local Bash script when I submit a form in orbeon?
Thanks
Calling Javascript:
You can call Javascript by adding the following inside your action:
<xxf:script>
//Add your script here
</xxf:script>
Calling a Java Servlet:
Create a submission: If you are using the Form Builder you can do it by creating a HTTP service, similar to the way a service is created in this link: http://wiki.orbeon.com/forms/how-to/fb-fr/call-service
If you are not using the Form Builder or prefer to write the submission manually:
<x:submission id="my-submission"
method=""
validate=""
relevant=""
resource="" replace="none" ../>
After creating a submission to call your Servlet, you have to send it from your action and it'll call the Servlet: <xf:send submission="my-submission"/>
http://wiki.orbeon.com/forms/doc/developer-guide/xforms-advanced-submissions
Action and Events
If you want to call it after submiting and saving the form and you are using Form Builder:
<xf:action ev:event="fr-data-save-done" ev:observer:"fr-form-model">
//Call the javascript or Servlet
</xf:action>
If you are not using Form Builder, just change ev:event/ev:observer according to your needs. xf:send also accepts these attributes.

Orbeon 4.3 doesn't seem to allow creation of new form with given ID

We have an application that creates new form runner forms in Orbeon. This is done by opening the URL to the form runner form.
Example:
http://server.com/orbeon/fr/[APP_NAME]/[FORM_NAME]/new/[new id]
In 3.8 and 3.9 we where able to give the [new id] and Orbeon would create a new form with the given ID.
In 4.3 however it doesn't seem to accept the [new id] any more.
We get this message in the browser:
You do not have access to this page.
It does allow us to generate new forms by using this url:
http://server.com/orbeon/fr/[APP_NAME]/[FORM_NAME]/new
But this doesn't give us control over the ID anymore.
We use the standard Exist persistence layer.
I'm not sure about the differences between 3.4 and 4.3, but in 4.3 the id can be passed as a URL parameter and then set using an action.
For example:
http://server.com/orbeon/fr/[APP_NAME]/[FORM_NAME]/new?document-id=[new id]
and include an action in the form definition:
<xf:model>
...
<xf:action id="populate-document-id-binding">
<xf:action ev:event="xforms-ready" ev:observer="fr-form-model" if="($fr-mode='new') and (xxf:get-request-parameter('document-id')!='')">
<xf:setvalue model="fr-parameters-model" ref="instance('fr-parameters-instance')/document" value="xxf:get-request-parameter('document-id')"/>
</xf:action>
</xf:action>
...
</xf:model>
This assumes you're happy with editing the form definition source.
DISCLAIMER: I don't know the road-map for the document parameter, so can't say how supportable this is going forward.

adding attributes to data.xml using xbl component in form builder

How can we send hint of Single-Line Text component, like xml attributes in Orbeon Form Builder to data.xml?
For example:
hint: first-name="Erik" last-name="Bruchez" email="info#orbeon.com"
<?xml version="1.0" encoding="utf-8" ?>
<form>
<contact first-name="Erik" last-name="Bruchez" email="info#orbeon.com" />
</form>
Now send button generate data.xml like :
<contact>
<first-name>Erik</first-name>
<last-name>Bruchez</last-name>
<email>info#orbeon.com</email>
<phone>6505555555</phone>
</contact>
Or maybe is there some ways to define data.xml attributes from Form Builder?
It look to me like you're trying to bind a control to an attribute (/form/contact/#first-name), instead of an element (/form/contact/first-name). You can do this if you write XForms by hand, but not if you're creating the form with Form Builder. With Form Builder, the structure of the XML used to collect the data is automatically created for you by Form Builder.
If this XML needs to go to another system that expects data in a different format, then you can, on submission, implement your own service to which the data is sent, and you can do the transformation in that service, for instance using XSLT.

Use of xi:include in Orbeon

I created a form using Orbeon form builder, and i included in its form instance the content of an xml file using :
<xi:include href="oxf:/path/file.xml" xxi:omit-xml-base="true" />
When i save the form in form builder and edit it, i get a new form, and when i publish it and run it in form runner i get a blank page.
Can you tell me please what's wrong with the xi:include ?
If you want to include the whole content of an external file as the instance, use:
<xforms:instance id="main-model-instance" src="oxf:/path/file.xml"/>
Here we have the model instance xml in external file at /path/file.xml and we are using this file into our form and have named the model instance as id="main-model-instance"
If you need to add part of the instance from external file, then insert that piece dynamically during xforms-model-construct-done event, e.g.:
<xforms:action ev:event="xforms-model-construct-done">
<!-- Extracts the element some-section from file.xml and uses it as the
root element of the fr-form-instance -->
<xforms:insert context="instance('fr-form-instance')"
origin="doc('oxf:/path/file.xml')/root-element/some-section" />
</xforms:action>

Resources