2

我们正在开发一个带有 xforms(带有 XSLTForms 客户端)和 BaseX 的应用程序,用于管理历史实体(参与者)并进行网络分析。在我们的一个表单中,我们填写了演员与其亲属之间的关系,我们希望在提交表单时为每个亲属创建并提交一个预填充的实例……</p>

…但我们对多次提交有问题。

基本上,我们有 3 个实例:

instance('entity'), 为主要形式

<xf:instance id="entity">
    <entity xmlns="">
        <name>John Doe</name>
        <age>35</age>
        <address>North Cap</address>
        <relations>
            <relation ref="" type="sibling">Elisa Doe</relation>
            <relation ref="" type="parent">Richard Doe</relation>
        </relations>
    </entity>
</xf:instance>

instance('newEntity')relation, 为每个in依次填写和发送instance('entity')(例如我们只是复制 name 值)

<xf:instance id="newEntity">
    <entity xmlns="">
        <name/>
        <age/>
        <address/>
        <relations>
            <relation ref="" type=""/>
        </relations>
    </entity>
</xf:instance>

instance('iterate'), 用于循环提交instance('newEntity')(when instance('iterate') = 1, we processrelation[position() = 1]

<xf:instance id="iterate">
    <iterate xmlns=""/>
</xf:instance>

这是我们的提交过程:

首先,我们用触发器启动循环,同时我们提交的relation值超过 ; 发送完所有关系后,我们提交主表单。instance('iterate')instance('newEntity')

<xf:trigger>
    <xf:label>submit</xf:label>
    <xf:action ev:event="DOMActivate">
        <xf:setvalue ref="instance('iterate')" value="1"/>
        <xf:setvalue ref="instance('newEntity')/name" value="instance('entity')/relations/relation[position() = instance('iterate')]"/>
        <xf:action while="count(//relation) &gt;= instance('iterate')">
            <xf:send submission="submitNewEntity"/>
            <xf:action if="count(//relation) &lt; instance('iterate')">
                <xf:send submission="submitEntity"/>
            </xf:action>
        </xf:action>
    </xf:action>
</xf:trigger>

然后我们提交了“新实体”。这里没什么特别的,提交完成后,我们relation/@ref根据服务器的响应,设置上一次提交对应的值,然后在instance('iterate')for循环中加“+1”。

<xf:submission ref="instance('newEntity')" id="submitNewEntity" resource="/test/form/put" method="put" replace="none">
    <xf:action ev:event="xforms-submit-done">
        <xf:message level="modal">
            OK 
            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:setvalue value="event('response-body')//*:id" ref="instance('entity')//relation[position() = instance('iterate')]/@ref"/>
        <xf:setvalue ref="instance('iterate')" value="instance('iterate') + 1"/>
    <xf:setvalue ref="instance('newEntity')/name" value="instance('entity')/relations/relation[position() = instance('iterate')]"/>
    </xf:action>
    <xf:action ev:event="xforms-submit-error">
        <xf:message level="modal">
            Error : <xf:output value="event('error-type')"/>; 
            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:submission>

最后,当所有关系都已保存后,我们将提交主表单

<xf:submission ref="instance('entity')" id="submitEntity" resource="/test/form/put" method="put" replace="none">
    <xf:action ev:event="xforms-submit-done">
        <xf:message level="modal">
            OK ! 
            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 : <xf:output value="event('error-type')"/>; 
            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:submission>

一切都很好,除了在每次提交之前 instance('newEntity'),我们都有一个提交错误,并显示一条错误消息:“submission-in-progress”。

事实上,在这个例子中,我不知道为什么,我们有 5 个提交而不是 3 个:

  • 2 关系“Elisa Doe”(第一个失败,第二个没问题)
  • 2 关系“Richard Doe”(第一个失败,第二个没问题)
  • 1 代表 John Doe(“主要”形式)

我们不知道如何避免这种情况,如果有人有想法,我们正在寻求帮助?

下面是两个完整的文件。

表格 :

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events">
    <head>
        <title>Submission</title>
        <xf:model>
            <xf:instance id="entity">
                <entity xmlns="">
                    <name>John Doe</name>
                    <age>35</age>
                    <address>North Cap</address>
                    <relations>
                        <relation ref="" type="sibling">Elisa Doe</relation>
                        <relation ref="" type="parent">Richard Doe</relation>
                    </relations>
                </entity>
            </xf:instance>

            <xf:instance id="newEntity">
                <entity xmlns="">
                    <name/>
                    <age/>
                    <address/>
                    <relations>
                        <relation ref="" type=""/>
                    </relations>
                </entity>
            </xf:instance>

            <xf:instance id="iterate">
                <iterate xmlns=""/>
            </xf:instance>

            <xf:submission ref="instance('entity')" id="submitEntity" resource="/test/form/put" method="put" replace="none">
                <xf:action ev:event="xforms-submit-done">
                    <xf:message level="modal">
                        OK ! 
                        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 : <xf:output value="event('error-type')"/>; 
                        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:submission>

            <xf:submission ref="instance('newEntity')" id="submitNewEntity" resource="/test/form/put" method="put" replace="none">
                <xf:action ev:event="xforms-submit-done">
                    <xf:message level="modal">
                        OK 
                        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:setvalue value="event('response-body')//*:id" ref="instance('entity')//relation[position() = instance('iterate')]/@ref"/>
                    <xf:setvalue ref="instance('iterate')" value="instance('iterate') + 1"/>
                </xf:action>
                <xf:action ev:event="xforms-submit-error">
                    <xf:message level="modal">
                        Error : <xf:output value="event('error-type')"/>; 
                        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:submission>

        </xf:model>
    </head>
    <body>
        <xf:input ref="name">
            <xf:label>name : </xf:label>
        </xf:input>
        <br />
        <xf:input ref="age">
            <xf:label>age : </xf:label>
        </xf:input>
        <br />
        <xf:input ref="address">
            <xf:label>address : </xf:label>
        </xf:input>
        <br />
        <xf:repeat nodeset="relations/relation" id="repeatRelation">
            <xf:input ref=".">
                <xf:label>Name : </xf:label>
            </xf:input>
            <xf:select1 ref="@type">
                <xf:item>
                    <xf:label>parent</xf:label>
                    <xf:value>parent</xf:value>
                </xf:item>
                <xf:item>
                    <xf:label>sibling</xf:label>
                    <xf:value>sibling</xf:value>
                </xf:item>
            </xf:select1>
            <xf:trigger>
                <xf:label>X</xf:label>
                <xf:action ev:event="DOMActivate">
                    <xf:delete ref="." at="1" if="count(//relation) > 1"/>
                </xf:action>
            </xf:trigger>
        </xf:repeat>
        <xf:trigger>
            <xf:label>Add relation</xf:label>
            <xf:action ev:event="DOMActivate">
                <xf:insert nodeset="relations/relation" at="last()"/>
                <xf:setvalue ref="relations/relation[index('repeatRelation')] | relations/relation[index('repeatRelation')]/@*"/>
            </xf:action>
        </xf:trigger>
        <br/>
        <xf:trigger>
            <xf:label>submit</xf:label>
            <xf:action ev:event="DOMActivate">
                <xf:setvalue ref="instance('iterate')" value="1"/>
                <xf:setvalue ref="instance('newEntity')/name" value="instance('entity')/relations/relation[position() = instance('iterate')]"/>
                <xf:action while="count(//relation) &gt;= instance('iterate')">
                    <xf:send submission="submitNewEntity"/>
                    <xf:action if="count(//relation) &lt; instance('iterate')">
                        <xf:send submission="submitEntity"/>
                    </xf:action>
                </xf:action>
            </xf:action>
        </xf:trigger>
    </body>
</html>

BaseX 的 Xquery 请求

xquery version "3.0";
module namespace test = "test";

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 namespace xf = "http://www.w3.org/2002/xforms";
declare namespace ev = "http://www.w3.org/2001/xml-events";

declare default element namespace "test";
declare default function namespace "test";

declare default collation "http://basex.org/collation?lang=fr";

declare variable $test:xsltFormsPath := "/test/files/xsltforms/xsltforms.xsl";


(:~
 : this function defines a static files directory for the app
 :
 : @param $file file or unknown path
 : @return binary file
 :)
declare
%rest:path('test/files/{$file=.+}')
function test:file($file as xs:string) as item()+ {
    let $path := file:base-dir() || 'files/' || $file
    return
        (
        web:response-header( map {'media-type' : web:content-type($path)}),
        file:read-binary($path)
        )
};

(:~
 : install db
 : @return create the db
 :
 : @todo create the prosopo db
 :)
declare 
  %rest:path("/test/install")
  %output:method("xml")
  %updating
function install() {
  if (db:exists("test")) 
    then (
      update:output("db 'test' already exists !")
     )
    else (
      update:output("db 'test' has been created"),
      db:create( "test", <root/>, "test.xml")
      )
};


(:~
 : This function returns db "test"
 :
 :)
declare
  %rest:path("/test")
  %output:method("xml")
function opendb() {
  db:open('test')
};


(:~
 : This function returns the entity form
 :
 :)
declare
  %rest:path("test/form")
  %output:method("xml")
function test() {
  fn:doc('files/submission.xml')
};

(:~
 : This function sends entity instance to db "test"
 : an @xml:id is created and sent to the form as http response
 : @param $param content
 :)

 declare
%rest:path("test/form/put")
%output:method("xml")
%rest:header-param("Referer", "{$referer}", "none")
%rest:PUT("{$param}")
%updating
function entityPut($param, $referer) {
  let $db := db:open("test")
  return 
    let $id := 'person' || fn:format-integer(fn:count($db/*:root/*:entity) + 1, '0000')
    let $param :=
      copy $d := $param
      modify insert node attribute xml:id {$id} into $d/*
      return $d
    return (
      insert node $param into $db/*:root,
      update:output(
         (
          <rest:response>
            <http:response status="200" message="">
              <http:header name="Content-Language" value="fr"/>
              <http:header name="Content-Type" value="text/plain; charset=utf-8"/>
            </http:response>
          </rest:response>,
          <result>
            <id>{$id}</id>
          </result>
         )
       )
    )
};

非常感谢你的帮助 !!

4

0 回答 0