跳转到内容

XQuery/简单 XForms 示例

来自维基教科书,开放书籍,开放世界

虽然静态 XForms 可以保存在 eXist 数据库中,但 XForms 也可以使用 XQuery 动态生成。在本节中,我们首先展示静态表单被一些 XForms 客户端引擎输出和执行,这些引擎包括 Firefox 插件、Javascript FormFaces 以及 XSLT/Javascript XSLTForms。

然后我们看看动态表单生成。

可以在 XForms 维基教科书 中找到各种各样的 XForms 示例。

XForms 引擎

[编辑 | 编辑源代码]

这些示例使用

  • Firefox 插件
    • 需要带有 XForms 插件的 Firefox
    • 媒体类型设置为 application/xhtml+xml
  • FormFaces
    • 跨浏览器支持 - 示例在 Firefox 和 IE6 上测试
    • Javascript 源代码存储在 eXist 数据库中,并链接到每个表单
    • 媒体类型设置为 text/html
  • XSLTForms
    • 使用 XSLT 转换为 HTML 页面,并使用 JavaScript 执行。
    • XSLT 转换可以是服务器端(通过 eXist)或客户端端。

所有示例都使用相同的 css 样式表

XForm 输出

[编辑 | 编辑源代码]
declare option exist:serialize "method=xhtml media-type=application/xhtml+xml indent=yes";

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:form="http://www.w3.org/2002/xforms" xml:lang="en">
   <head>
      <title>Output a Model value</title>
         <form:model>
            <form:instance>
                <data xmlns="">
                    <name>Mozilla XForms add-in</name>
               </data>
            </form:instance>
        </form:model>
   </head> 
   <body>
       <h2>
             <form:output ref="name"></form:output>
       </h2>
   </body>
</html>

执行

FormFaces

[编辑 | 编辑源代码]
declare option exist:serialize "method=xhtml media-type=text/html indent=yes";

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:form="http://www.w3.org/2002/xforms" xml:lang="en">
   <head>
      <title>Output a Model value</title>
         <script language="javascript" src="../formfaces/formfaces.js"/>
         <link rel="stylesheet" type="text/css" href="xforms.css" />
         <form:model>
            <form:instance>
                <data xmlns="">
                    <name>Formfaces</name>
               </data>
            </form:instance>
        </form:model>
   </head> 
   <body>
       <h2>
             <form:output ref="name"></form:output>
       </h2>
   </body>
</html>

执行

XSLTForms

[编辑 | 编辑源代码]
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="ajaxforms.xsl" type="text/xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:form="http://www.w3.org/2002/xforms" xml:lang="en">
   <head>
      <title>Output a Model value</title>
         <script language="javascript" src="formfaces.js"/>
         <link rel="stylesheet" type="text/css" href="xforms.css" />
         <form:model>
            <form:instance>
                <data xmlns="">
                    <name>Formfaces</name>
               </data>
            </form:instance>
        </form:model>
   </head> 
   <body>
       <h2>
             <form:output ref="name"></form:output>
       </h2>
   </body>
</html>

执行

简单控件

[编辑 | 编辑源代码]

Firefox Formfaces XSLTForms

  • FormFaces : 在 Firefox 上中断
  • XSLTForms : 仅在触发时进行更改

多实例

[编辑 | 编辑源代码]

一个模型可以包含多个实例,这些实例的根节点可以通过 instance(id) 结构访问。

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" 
      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">
   <head>
      <title>Test conditional selection lists</title>
      <xf:model>
         <xf:instance id="data" xmlns="">
            <data>
               <selected-season>spring</selected-season>
               <selected-month>March</selected-month>
            </data>
         </xf:instance>
         <xf:instance id="seasons" xmlns="">
            <seasons>
               <item name="winter"/>
               <item name="spring"/>
               <item name="summer"/>
               <item name="autumn"/>    
            </seasons>
         </xf:instance>
         <xf:instance id="months" xmlns="">
            <months>
               <item name="January" season="winter"/>
               <item name="February" season="winter"/>
               <item name="March" season="spring"/>
               <item name="April" season="spring"/>
               <item name="May" season="spring"/>
               <item name="June" season="summer"/>
               <item name="July" season="summer"/>
               <item name="August" season="summer"/>
               <item name="September" season="autumn"/>
               <item name="October" season="autumn"/>
               <item name="November" season="autumn"/>
               <item name="December" season="winter"/>
            </months>
         </xf:instance>
      </xf:model>
   </head>
   <body>
      <p>Test conditional selection lists - 
         month selector depends on the current season</p>   
      <div>
         <xf:select1 ref="instance('data')/selected-season">
           <xf:label>Season:</xf:label>
           <xf:itemset nodeset="instance('seasons')/item">
             <xf:label ref="@name"/>
             <xf:value ref="@name"/>
           </xf:itemset>            
         </xf:select1>
      </div>
      <div>
         <xf:select1 ref="instance('data')/selected-month">
           <xf:label>Month:</xf:label>
           <xf:itemset nodeset="instance('months')/item[@season=instance('data')/selected-season]">
             <xf:label ref="@name"/>
             <xf:value ref="@name"/>
           </xf:itemset>            
         </xf:select1>
      </div>
      <div>
         <xf:output ref="instance('data')/selected-season">
            <xf:label>selected-season: </xf:label>
         </xf:output>
         <xf:output ref="instance('data')/selected-month">
            <xf:label>selected-month: </xf:label>
         </xf:output>
      </div>
   </body>
</html>

FireFox

日期输入

[编辑 | 编辑源代码]
  • Firefox 生成一个下拉日历。 Firefox
  • Formfaces 目前没有日历小部件 Formfaces

服务器交互

[编辑 | 编辑源代码]

与服务器的交互可以通过 GET 或 POST 进行。此示例基于 Dan McCreary 在 XForms 维基教科书 中的示例。

在 Firefox 上

<html xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>XQuery Tester</title>
         <link rel="stylesheet" type="text/css" href="xforms.css" />
    
        <xf:model>
            <xf:instance>
                <data xmlns="">
                  <input>
                    <arg1>123</arg1>
                    <arg2>456</arg2>
                </input>
                <result>
                    <sum>0</sum>
                 </result>
                 </data>
            </xf:instance>
            
            <xf:submission id="get-instance"  method="get" replace="instance" 
                action="adderGet.xq"
                separator="&">
            </xf:submission>          
            
            <xf:submission id="post-instance" method="post"  replace="instance"
                 action="adderPost.xq">
            </xf:submission>
            
         </xf:model>
    </head>
    <body>
        <h1>XForm interaction with XQuery</h1>
        <xf:input ref="input/arg1" incremental="true">
            <xf:label>Arg1:</xf:label>
        </xf:input>
        <br/>
        <xf:input ref="input/arg2" incremental="true">
            <xf:label>Arg2:</xf:label>
        </xf:input>
        <br/>
        <xf:output ref="result/sum">
            <xf:label> Sum:</xf:label>
        </xf:output>
        <br/>
        
        <xf:submit submission="get-instance">
            <xf:label>Get</xf:label>
        </xf:submit>
        
        <xf:submit submission="post-instance">
            <xf:label>Post</xf:label>
        </xf:submit>
        <p id="status"></p>
    </body>
</html>

Firefox Formfaces


相应的服务器脚本是

  • GET
xquery version "1.0";
declare namespace request="http://exist-db.org/xquery/request";

let $arg1 := number(request:get-parameter("arg1", "0"))
let $arg2 := number(request:get-parameter("arg2", "0"))
return
<data xmlns="">
  <input>
    <arg1>{$arg1}</arg1>
    <arg2>{$arg2}</arg2>
  </input>
  <result>
     <sum>{$arg1+$arg2}</sum>
   </result>
</data>

  • POST
xquery version "1.0";
declare namespace request="http://exist-db.org/xquery/request";

let $data := request:get-data()

let $arg1 := number($data/arg1)
let $arg2 := number($data/arg2)
return
<data xmlns="">
  <input>
    <arg1>{$arg1}</arg1>
    <arg2>{$arg2}</arg2>
  </input>
  <result>
     <sum>{$arg1+$arg2}</sum>
   </result>
</data>

在此示例中,整个模型都会被更新并返回给客户端。或者,可以更新模型的一部分(待续)


通用 XForms

[编辑 | 编辑源代码]

表格示例

[编辑 | 编辑源代码]

此脚本基于 XForms 维基教科书中的一个示例,说明了通用 XForms 的一种简单方法。

declare option exist:serialize "method=xhtml media-type=application/xhtml+xml indent=yes";

let $data :=           
<Data>
               <GivenName>John</GivenName>
               <MiddleName>George</MiddleName>
               <Surname>Doe</Surname>
               <CityName>Anytown</CityName>
               <StateCode>MM</StateCode>
               <PostalID>55123-1234</PostalID>
</Data>
return

<html xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Formatting XForms</title>
        <link rel="stylesheet" type="text/css" href="xforms.css" />

        <style type="text/css">
{
  for $item in $data/*
  let $width := string-length($item) 
  return concat('._',name($item),' .xf-value {width:', $width,'em}
')
}
   </style>
      <xf:model>
         <xf:instance xmlns="">
           {$data}
          </xf:instance>
      </xf:model>
   </head>
   <body>
      <fieldset>
      <legend>Name and Address</legend>
      {for $item in $data/*
       return 
        (
       <xf:input class="_{name($item)}" ref="/Data/{name($item)}">
         <xf:label>{name($item)}:  </xf:label>
       </xf:input>,
        <br/>
        )
     }
       </fieldset>
     </body>
</html>

在这个简单的表格示例中,XForm 和用于定义输入字段宽度的配套 CSS 是通过对提供的实例进行反射生成的。

此示例在 Firefox 中正常工作,但在 Formfaces 中样式失败


简单表单架构

[编辑 | 编辑源代码]

一个简单的架构可以提供对生成的 XForms 的更多控制。此示例仍然用于简单的表格结构

declare option exist:serialize "method=xhtml media-type=application/xhtml+xml indent=yes";

let $data :=           
<Data>
               <GivenName>John</GivenName>
               <MiddleName>George</MiddleName>
               <Surname>Doe</Surname>
               <CityName>Anytown</CityName>
               <StateCode>MM</StateCode>
               <PostalID>55123-1234</PostalID>
 </Data>
 
 let $schema := 
 <Schema>
     <Row name="GivenName" label="First Name" width="20"/>
     <Row name="Surname" label="Surname" width="15"/>
     <Row name="CityName" label="City" width="15"/>
     <Row name="StateCode" label="State" width="3"/>
    <Row name="PostalID" label="ZipCode" width="8"/>
 </Schema>
return

<html xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Formatting XForms</title>
        <link rel="stylesheet" type="text/css" href="xforms.css" />

        <style type="text/css">
{
  for $item in $schema/*
  let $id := concat("_",$item/@name)
  let $width := $item/@width 
  return concat('.',$id,' .xf-value {width:', $width,'em}
')
}
   </style>
      <xf:model>
         <xf:instance xmlns="">
           {$data}
          </xf:instance>
      </xf:model>
   </head>
   <body>
      <fieldset>
      <legend>Name and Address</legend>
      {for $item in $schema/*
        let $id := concat("_",$item/@name)
        let $label := string( $item/@label)
       return 
        (
       <xf:input class="{$id}" ref="/Data/{$item/@name}">
         <xf:label>{$label}:  </xf:label>
       </xf:input>,
        <br/>
        )
     }
       </fieldset>
     </body>
</html>

Firefox

华夏公益教科书