Skip to content

Instantly share code, notes, and snippets.

@sardinecan
Created February 6, 2021 08:35
Show Gist options
  • Save sardinecan/64451cf122095178159804e1ea13b4e5 to your computer and use it in GitHub Desktop.
Save sardinecan/64451cf122095178159804e1ea13b4e5 to your computer and use it in GitHub Desktop.
[Xforms-XSLTForms] Submission loop
<?xml-stylesheet href="xsltforms.xsl" type="text/xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xpr="xpr" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" lang="fr" xpr:bogus="fix Firefox namespace issue">
<head>
<title>Submission loop with Xforms</title>
<xf:model id="model">
<xf:instance id="main">
<person xmlns="xpr">
<name>John Doe</name>
<relations>
<relation ref="local-id-person1"/>
<relation ref="local-id-person2"/>
<!--<relation ref="local-id-person3"/>-->
</relations>
</person>
</xf:instance>
<xf:instance id="sub">
<listPerson xmlns="xpr">
<person id="pers1">Mick</person>
<person id="pers2">Keith</person>
<person id="pers3">Charlie</person>
<person id="pers4">Bill</person>
<person localType="new" id="local-id-person1">Brian</person>
<person localType="new" id="local-id-person2">Daryl</person>
<!--<person localType="new" id="local-id-person3"></person>-->
</listPerson>
</xf:instance>
<xf:instance id="sup">
<supplement xmlns="xpr">
<relation ref=""/>
<person localType="new" id=""/>
</supplement>
</xf:instance>
<xf:bind nodeset="instance('main')/xpr:name" required="true()"/>
<xf:bind nodeset="instance('sub')/xpr:person" required="true()"/>
<xf:action ev:event="submission">
<xf:send if="instance('sub')/xpr:person[@localType='new']" submission="submitNewPerson"/>
<!--<xf:send if="not(instance('xprEntities')/xpr:entity[@localType='new'][@xml:id=instance('xprProsopo')//@xlink:href[. != '']]) and instance('xprSources')/xpr:source[@localType = 'new'][@xml:id[. != ''] = instance('xprProsopo')//xpr:source/@xlink:href]" submission="submitNewSource"/>-->
<xf:send if="not(instance('sub')/xpr:person[@localType='new'])" submission="submitBio"/>
</xf:action>
<xf:submission
mode="synchronous"
id="submitNewPerson"
ref="instance('sub')/xpr:person[@localType='new']"
resource="/xforms/person/put"
method="put"
replace="none">
<xf:action ev:event="xforms-submit-done">
<xf:setvalue ref="instance('sub')/xpr:person[@id=normalize-space(event('response-body')//xpr:xforms-id)]/@id"
value="event('response-body')//xpr:id"/>
<xf:setvalue ref="instance('main')//@ref[normalize-space(.)=normalize-space(event('response-body')//xpr:xforms-id)]"
value="event('response-body')//xpr:id"/>
<xf:setvalue ref="instance('sub')/xpr:person[@id=normalize-space(event('response-body')//xpr:id)]/@localType"
value="'stored'"/>
<xf:message level="modal">
Submission done!
Status : <xf:output value="event('response-status-code')"/>;
URI : <xf:output value="event('resource-uri')"/>;
Headers : <xf:output value="event('response-headers')"/>;
Reason : <xf:output value="event('response-reason-phrase')"/>;
Body : <xf:output value="event('response-body')"/>.
</xf:message>
<xf:dispatch name="submission" targetid="model" delay="1"/>
</xf:action>
<xf:action ev:event="xforms-submit-error">
<xf:message level="modal">
error!
error-type: <output value="event('error-type')"/>
error-message: <output value="event('error-message')"/>
response-status-code: <output value="event('response-status-code')"/>
response-reason-phrase: <output value="event('response-reason-phrase')"/>
resource-uri: <output value="event('resource-uri')"/>
</xf:message>
</xf:action>
</xf:submission>
<xf:submission
mode="synchronous"
id="submitBio"
ref="instance('main')"
resource="/xforms/bio/put"
method="put"
replace="none">
<xf:action ev:event="xforms-submit-done">
<xf:message level="modal">
Submission done!
Status : <xf:output value="event('response-status-code')"/>;
URI : <xf:output value="event('resource-uri')"/>;
Headers : <xf:output value="event('response-headers')"/>;
Reason : <xf:output value="event('response-reason-phrase')"/>;
Body : <xf:output value="event('response-body')"/>.
</xf:message>
</xf:action>
<xf:action ev:event="xforms-submit-error">
<xf:message level="modal">
error!
error-type: <output value="event('error-type')"/>
error-message: <output value="event('error-message')"/>
response-status-code: <output value="event('response-status-code')"/>
response-reason-phrase: <output value="event('response-reason-phrase')"/>
resource-uri: <output value="event('resource-uri')"/>
</xf:message>
</xf:action>
</xf:submission>
</xf:model>
</head>
<body>
<xf:group ref="instance('main')">
<xf:input ref="xpr:name">
<xf:label>Name</xf:label>
</xf:input>
<xf:group ref="xpr:relations">
<xf:label>Relations</xf:label>
<xf:repeat nodeset="xpr:relation">
<xf:var name="relation" value="."/>
<xf:label>Relation</xf:label>
<xf:group ref="@ref[.!='' and .=instance('sub')/xpr:person[@localType='new']/@id]">
<xf:trigger>
<xf:label>person in instance</xf:label>
<xf:setvalue ref="." value="''" ev:event="DOMActivate"/>
</xf:trigger>
</xf:group>
<xf:group ref="@ref[.='' or . = instance('sub')/xpr:person[not(@localType='new')]/@id]">
<xf:trigger>
<xf:label>new personne</xf:label>
<xf:insert context="instance('sub')"
origin="instance('sup')/xpr:person"
nodeset="xpr:person[1]"
position="before"
ev:event="DOMActivate"/>
<!-- set a temporary xml:id value for added entity -->
<xf:setvalue ref=".
| instance('sub')/xpr:person[@localType = 'new'][@id = '']/@id"
value="concat('local-id-person', number(count(instance('sub')/xpr:person[@localType = 'new'])))"
ev:event="DOMActivate"/>
</xf:trigger>
<xf:select1 ref=".">
<xf:label>Name</xf:label>
<xf:itemset nodeset="instance('sub')/xpr:person">
<xf:label ref="."/>
<xf:value ref="@id"/>
</xf:itemset>
</xf:select1>
</xf:group>
<xf:group ref="instance('sub')/xpr:person[@id = $relation/@ref]">
<xf:input ref=".">
<xf:label>name</xf:label>
</xf:input>
</xf:group>
</xf:repeat>
<xf:trigger>
<xf:label>Add relation</xf:label>
<xf:insert
ev:event="DOMActivate"
context="."
origin="instance('sup')/xpr:relation"
nodeset="xpr:relation"
at="last()"
position="after"/>
</xf:trigger>
</xf:group>
</xf:group>
<xf:trigger>
<xf:label>Save</xf:label>
<xf:action ev:event="DOMActivate">
<xf:dispatch name="submission" targetid="model"/>
</xf:action>
</xf:trigger>
</body>
</html>
xquery version "3.0";
module namespace xpr = "xpr";
(:~
:
: @author sardinecan
: @since 2021-02
:
:)
declare namespace rest = "http://exquery.org/ns/restxq";
declare namespace file = "http://expath.org/ns/file";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace web = "http://basex.org/modules/web";
declare namespace update = "http://basex.org/modules/update";
declare namespace db = "http://basex.org/modules/db";
declare default element namespace "xpr";
declare default function namespace "xpr";
declare namespace xlink = "http://www.w3.org/1999/xlink" ;
declare namespace ev = "http://www.w3.org/2001/xml-events" ;
declare namespace xf = "http://www.w3.org/2002/xforms" ;
declare default collation "http://basex.org/collation?lang=fr";
(:~
: This resource function install app
: @return create the db
:)
declare
%rest:path("xforms/install")
%output:method("xml")
%updating
function xformsInstall() {
update:output("Xforms database created"),
db:create( "xforms", <xpr xmlns='xpr'><bio></bio><listPerson></listPerson></xpr>, "xforms.xml", map {"chop" : fn:false()} )
};
(:~
: This function creates new entry in db
: @param $param content to insert in the database
: @param $refere the callback url
: @return update the database and send result message to xforms
:)
declare
%rest:path("xforms/bio/put")
%output:method("xml")
%rest:header-param("Referer", "{$referer}", "none")
%rest:PUT("{$param}")
%updating
function xformsBio($param, $referer) {
let $db := db:open("xforms")
return (
insert node $param into $db/xpr/bio,
update:output((
<result>
<message>Submission done: {fn:normalize-space($param)}</message>
</result>))
)
};
(:~
: This function creates new entry in list person
: @param $param content to insert in the database
: @param $refere the callback url
: @return update the database and send result message to xforms
:)
declare
%rest:path("xforms/person/put")
%output:method("xml")
%rest:header-param("Referer", "{$referer}", "none")
%rest:PUT("{$param}")
%updating
function xformsPerson($param, $referer) {
let $db := db:open("xforms")
let $xforms := fn:normalize-space($param//@id)
let $id := fn:generate-id($param)
return (
insert node $param into $db/xpr/listPerson,
update:output((
<result>
<xforms-id>{$xforms}</xforms-id>
<id>{$id}</id>
<message>Submission done: {fn:normalize-space($param)}</message>
</result>))
)
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment