XForms/eXist
eXist 是一个具有完整 REST 接口的原生 XML 数据库。 这使您可以使用 eXist 保存表单数据,而无需编写任何中间件粘合代码。
eXist 提供了一个完整的 REST 接口,可以轻松地从 XForm 调用。
eXist 还提供了一个完整的 WebDAV 接口。 这使您可以直接从表单执行 HTTP “PUT” 操作。
在本示例中,我们将创建一个名为“juser”(Jane User)的用户,并设置一个集合来读取和写入表单数据。
要运行此程序,只需从 [1] 网站安装 eXist。 使用 eXist 管理菜单创建一个名为“juser”的用户。 然后在 /db/home/juser 为 juser 创建一个主页集合。 然后以 juser 身份登录并创建一个名为“test”的集合。 您将在此文件中放置表单和实例数据。
要将实例数据读写到表单中,只需使用以下示例
<html>
<head>
<xf:model>
<xf:instance id="data-instance" src="data.xml" xmlns=""/>
<xf:submission id="read-from-file"
method="get"
action="https://127.0.0.1:8080/exist/rest/db/home/juser/test/data.xml"
replace="instance" instance="data-instance"/>
<xf:submission id="save-to-file"
method="put"
action="https://127.0.0.1:8080/exist/webdav/db/home/juser/test/data.xml"
replace="instance" instance="data-instance"/>
</xf:model>
</head>
...
请注意,如果数据与表单位于同一个集合中(不是一个好的长期设计),则可以使用相对路径引用。 还要注意,我们正在对 eXist 的webdav(而不是 rest)接口执行 HTTP PUT 操作。
将 XML 数据直接加载到您的 XForms 应用程序中很容易。 在模型中的实例语句中,只需添加一个src 属性,并放置您要编辑的文件的路径名。 关键是将“rest”一词放在 URL 中,当您将数据读入表单时
<xf:instance id="my-form-data" xmlns="" src="https://127.0.0.1:8080/exist/rest/db/home/juser/test/data.xml"/>
在执行 HTTP PUT 时,请始终在 URL 路径中添加“webdav”一词。
https://127.0.0.1:8080/exist/webdav/db/home/juser/test/data.xml
就这么简单!
有关更多信息,请参阅 eXist 手册,了解如何使用 eXist 的 REST 和 WebDAV 接口。
使用 XML 数据库时,有时您希望数据库接收 XML 文档并根据业务规则(例如 XML 文档的内容和日期)将其存储在正确的位置。 这可以在关系数据库中使用存储过程来完成。
XQuery 可以被认为是面向 XML 的存储过程。 eXist 允许您直接保存到 XQuery 的 URL,并且 XQuery 可以根据许多规则存储文档。
这是一个 eXist XQuery 示例,它接收 HTTP POST 并根据输入文档中的县和日期创建一个集合的路径名。 在保存文件并检查保存是否成功后,它会增加一个计数器,类似于某些关系数据库的 AUTOINCREMENT 属性。
xquery version "1.0";
(: Save-crv.xq Version 0.1, Dan McCreary, March 2nd 2007:)
declare namespace request="http://exist-db.org/xquery/request";
declare namespace xmldb="http://exist-db.org/xquery/xmldb";
declare namespace c="http://niem.gov/niem/common/1.0" ;
declare namespace u="http://niem.gov/niem/universal/1.0" ;
declare namespace mn="http://data.state.mn.us" ;
declare namespace mnr="http://revenue.state.mn.us" ;
declare namespace mnr-ptx="http://propertytax.state.mn.us" ;
declare namespace xsi="http://www.w3.org/2001/XMLSchema-instance";
(: to store a CRV into the right location in exist we need 1) the county ID, 2) the date, 3) the sequence number :)
(: get the data from an HTTP post :)
let $crv := request:get-data()
let $count := count($crv//node())
let $county-id := $crv//eCRVDocument/RealProperty/RealPropertyLegalDescriptions/mnr-ptx:MNCountyID/text()
(: let $county-id := '19' :)
let $current-year := substring(string(current-date()),1, 4)
let $current-year-2 := substring(string(current-date()),3, 2)
(: let $collection := xmldb:collection(concat('xmldb:exist:///db/crv/data', $county-id, '/', $current-year), "dan", "dan123") :)
let $county-name := doc('/db/crv/data/admin/next-county-crvid.xml')//County[CodeID=$county-id]/Code
(: get the next-id from the sequence counter :)
let $next-id := doc('/db/crv/data/admin/next-county-crvid.xml')//County[CodeID=$county-id]/NextID
let $file-name := concat($next-id, '.xml')
let $collection-string := concat('xmldb:exist:///db/crv/data/', $county-name, '/', $current-year)
let $full-path := concat($collection-string, '/', $file-name)
(: ready to login and store a file :)
let $collection := xmldb:collection($collection-string, "login", "password")
let $retStore := xmldb:store($collection-string, $file-name, <eCRVDocument>{$crv/*}</eCRVDocument>)
(: If the file that we attempted to store does eXist, then now it is OK to increment the sequence counter for the next user :)
let $retCode1 := if (doc($full-path))
then ( update replace doc("/db/crv/data/admin/next-county-crvid.xml")//County[CodeID=$county-id]/NextID with
<NextID>{$next-id + 1}</NextID> )
else ()
return
<data>
<county-id>{$county-id}</county-id>
<current-year>{$current-year-2}</current-year>
<sequence-id>{$next-id - 1}</sequence-id>
</data>
此 XQuery 返回一个 XML 消息,例如以下内容
<data>
<county-id>19</county-id>
<current-year>07</current-year>
<sequence-id>47</sequence-id>
</data>
假设您已设置主机名、端口和应用程序名称变量,则 XForms 应用程序将包含以下代码
<xf:model>
...
<xf:submission id="submit-validate-a1" method="post"
action="http://{$hostname}:{$exist-port}/{$application-name}/submit"
replace="instance" instance="submit-result">
<xf:toggle case="case-busy" ev:event="xforms-submit" />
<xf:toggle case="case-submit-error" ev:event="xforms-submit-error" />
<xf:toggle case="case-done" ev:event="xforms-submit-done" />
</xf:submission>
...
</xf:model>
...
<body>
...
<xf:case id="case-done">
<xf:group ref="instance('submit-result')">
<h1 class="result-text">Your ID is =
<xf:output ref="county-id"/>-<xf:output ref="current-year"/>-<xf:output ref="sequence-id"/></h1>
</xf:group>
...
</xf:case>
如果您希望您的 XQuery 返回正确的 mime 类型,请在序言中添加以下内容
declare option exist:serialize "method=xhtml media-type=text/xml indent=yes omit-xml-declaration=no";
declare namespace util="http://exist-db.org/xquery/util";
...
let $ret-code := util:declare-option("exist:serialize", "media-type=text/xml")
(Kurt Cagle 的建议)
declare option exist:serialize "method=3Dxhtml indent=3Dyes
omit-xml-declaration=3Dno
doctype-public=3D-//W3C//DTD XHTML 1.1//EN
doctype-system=3Dhttp://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd";