跳到内容

XForms/从文件中选择代码

来自 Wikibooks,开放的书籍,开放的世界
最佳实践

设计表单的人员经常需要维护许多代码表。这些代码表可能会经常更改,并且可能存在更新中心维护的代码表数据库的流程。因此,您希望每个表单都能够动态地从 XML 文件或 RESTful 网络服务中获取当前相关的代码。

此示例程序演示了如何直接从文件或代码表网络服务中读取带标签的代码列表。在此示例中,包含代码的文件只是一个格式良好的 XML 文件,它位于与表单相同的目录中。

从本地文件或网络服务加载 XML 实例数据

[编辑 | 编辑源代码]

以下代码片段,通常位于 HTML 头部,演示了如何使用实例的“src”属性从与表单相同的目录中的本地文件读取 XML 数据。

将单个代码表加载到单个实例中

[编辑 | 编辑源代码]
<html>
   <xf:model>
      <xf:instance src="XMLSchemaTypeCode.xml" id="XMLSchemaTypeCode"/>
   </xf:model>
</html>

从网络服务加载代码

[编辑 | 编辑源代码]

通常使用单个网络服务来加载所有代码表。此服务可以传递参数,例如代码表的名称以及人员所属的组。这可以缩短长列表中的选择列表。

<html>
   <xf:model>
      <xf:instance id="ApprovalCodes" src="/db/mdr/services/all-codes.xq?code=ApprovalCodes&group=editor"/>
   </xf:model>
</html>

将所有代码加载到单个实例中

[编辑 | 编辑源代码]

将单个代码表加载到单个实例中的问题是,您必须对每个代码表执行单独的 HTTP 获取操作。对于具有一个或两个小型选择列表的表单,这不成问题。但是,对于具有许多选择列表的大型表单,这会减慢表单响应时间。解决方案是通过单个 HTTP GET 请求将所有代码加载到单个实例中。然后可以从该实例中选择每个代码表。

<html>
   <xf:model>
      <xf:instance id="code-tables" src="/db/mdr/services/all-codes.xq?form=DataElementManager&group=admin"/>
   </xf:model>
</html>

在第二个示例中,表单中的所有代码都由元数据注册表 (MDR) 的服务生成。此服务器返回的数据是表单中每个 select1 控件的代码集合。

这将查找当前目录中的格式良好的 XML 文件,并将其加载到模型实例中。

请注意,在这种情况下,模型被赋予了 ID。这是为了允许多个代码表分别读入各自的单独模型。

屏幕图像

[编辑 | 编辑源代码]

以下是对程序的屏幕图像。当用户从下拉列表中选择时,输出的值会立即更新。

请注意,屏幕上的标签与存储在模型中的标签不同。

示例程序

[编辑 | 编辑源代码]
<html
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:xf="http://www.w3.org/2002/xforms" >
   <head>
      <title>Select List From File</title>
      
      /* the default model */
      <xf:model>
         <xf:instance id="save-data" xmlns="">
            <data>
                  <MyXMLSchemaTypeCode/>
            </data>
         </xf:instance>
         <xf:instance id="code-tables" src="XMLSchemaTypeCode.xml"/>
      </xf:model>
      
   </head>
   <body>
      <p>This selection list was read from a file.</p>
      <xf:select1  ref="/MyData/MyXMLSchemaTypeCode">
         <xf:label>Select XML Schema data type: </xf:label>
         <xf:itemset ref="instance('code-tables')/XMLSchemaTypeCode/item">
            <xf:label ref="label"/>
            <xf:value ref="value"/>
         </xf:itemset>
      </xf:select1>
      <br/>
      <xf:output ref="instance('save-data')/MyXMLSchemaTypeCode">
         <xf:label>Value of MyXMLSchemaTypeCode: </xf:label>
      </xf:output>
   </body>
</html>

示例 XML 数据

[编辑 | 编辑源代码]
<?xml version="1.0" encoding="UTF-8"?>
<XMLSchemaTypeCode>
   <label>XML Schema Type:</label>
   <item>
      <label>Date and Time</label>
      <value>dateTime</value>
   </item>
   <item>
      <label>Time (HH:MM:SS-06:00)</label>
      <value>time</value>
   </item>
   <item>
      <label>Date (yyyy-mm-dd)</label>
      <value>date</value>
   </item>
   <item>
      <label>Year and Month</label>
      <value>gYearMonth</value>
   </item>
   <item>
      <label>Year (nnnn)</label>
      <value>gYear</value>
   </item>
   <item>
      <label>Month and Day</label>
      <value>gMonthDay</value>
   </item>
   <item>
      <label>Day of Month (1 .. 31)</label>
      <value>gDay</value>
   </item>
   <item>
      <label>Month (1 .. 12)</label>
      <value>gMonth</value>
   </item>
   <item>
      <label>String</label>
      <value>string</value>
   </item>
   <item>
      <label>Boolean (true/false)</label>
      <value>boolean</value>
   </item>
   <item>
      <label>Base 64 Binary</label>
      <value>base64Binary</value>
   </item>
   <item>
      <label>Decimal (0.00)</label>
      <value>decimal</value>
   </item>
   <item>
      <label>Any URI</label>
      <value>anyURI</value>
   </item>
   <item>
      <label>Integer (...,-2,-1,0,1,2,...)</label>
      <value>integer</value>
   </item>
   <item>
      <label>Non-Positive Integer (...,-2,-1,0)</label>
      <value>nonPositiveInteger</value>
   </item>
   <item>
      <label>Negative Integer (...,-2,-1)</label>
      <value>negativeInteger</value>
   </item>
   <item>
      <label>Long (-9,223,372T .. 9,223,372T)</label>
      <value>long</value>
   </item>
   <item>
      <label>Int (-2,147,483,648 .. 2,147,483,647)</label>
      <value>int</value>
   </item>
   <item>
      <label>Short (-32,768 .. 32,767)</label>
      <value>short</value>
   </item>
   <item>
      <label>Byte (-128 .. 127)</label>
      <value>byte</value>
   </item>
   <item>
      <label>Non-negative Integer (0..N)</label>
      <value>nonNegativeInteger</value>
   </item>
    <item>
      <label>Positive Integer (1..N)</label>
      <value>positiveInteger</value>
   </item>
   <item>
      <label>Unsigned Long (0 .. 18,446,744T)</label>
      <value>unsignedLong</value>
   </item>
   <item>
      <label>Unsigned Int (0 .. 4,294,967,295)</label>
      <value>unsignedInt</value>
   </item>
   <item>
      <label>Unsigned Short (0.. 65,535)</label>
      <value>unsignedShort</value>
   </item>
   <item>
      <label>Unsigned Byte (0..255)</label>
      <value>unsignedByte</value>
   </item>
</XMLSchemaTypeCode>

请注意,要格式良好,XML 文件必须包含一个根数据元素,该元素必须与节点集参数匹配。

从 XML REST 网络服务中提取数据

[编辑 | 编辑源代码]

您可以将实例src属性替换为指向 XML REST 网络服务的直接路径。例如,如果您将所有代码表都放在项目资源集合中,则路径看起来如下所示

<xf:instance src="../resources/code-tables/PersonGenderCode.xml"/>

或者,如果您的系统代码存储在单个 XML 文件中,并且您有一个包装器 XQuery,则

<xf:instance src="../resources/code-tables/get-codes-for.xq?element=PersonGenderCode"/>

从单个实例中选择列表

[编辑 | 编辑源代码]

为了使您的表单保持快速,通常最好对所有代码执行一次 HTTP GET 操作。如果每个列表都执行单独的 HTTP GET 操作,则具有许多选择列表的表单加载时间会很长。对于大型表单,可以轻松地将表单加载时间提高 10 倍。

代码表实例的结构

[编辑 | 编辑源代码]

以下是加载到单个实例中的所有代码的示例结构

<xf:instance id="code-tables">
   <code-tables>
      <code-table>
         <code-table-name>MyElementCode</code-table-name>
         <items>
            <item>
               <label>Joe Smith</label>
               <value>42</value>
            </item>
            <item>
               <label>Sue Johnson</label>
               <value>47</value>
            </item>
         <items>
      </code-table>
      <code-table>
         <code-table-name>ColorCode</code-table-name>
         <items>
            <item>
               <label>Red</label>
               <value>1</value>
            </item>
            <item>
               <label>Orange</label>
               <value>2</value>
            </item>
         <items>
      </code-table>
   </code-tables>
</xf:instance>

示例 Select1

[编辑 | 编辑源代码]

将数据加载到模型后,每个select1select控件都可以使用xf:itemset元素直接从模型中获取数据。Itemset 的工作方式与 repeat 相同,并使用 nodeset(而不是 ref)来获取所有值。以下是如何从代码表实例中获取 itemset 数据的示例。

<xf:select1 ref="instance('save-data')/MyElementName">
   <xf:label>My Element:</xf:label>
   <xf:itemset nodeset="instance('code-tables')/code-table[code-table-name='MyElementCode']/items/item">
       <xf:label ref="label"/>
       <xf:value ref="value"/>
   </xf:itemset>
</xf:select1>

请注意,谓词 [code-table-name='MyElementCode'] 仅将该代码的项目放入选择列表中。

从元数据注册表自动生成代码表

[编辑 | 编辑源代码]

由于 XML Schema 不包含表示信息,因此我们使用以下工作流作为“最佳实践”。

  1. 将所有标签/值对存储在外部代码表文件中,或从网络服务中获取此信息。
  2. 对于每个表单,创建一个网络服务,该服务将为表单中使用的所有代码生成代码表元素。
  3. 将代码表元素加载到模型中的一个单独的实例中,并将其 ID 设置为“code-tables”。
  4. 通过获取具有该名称的代码表来从该实例中选择每个 select1 或 select 元素的代码表。

当需要将一组共享通用代码的复杂表单放置在自己的目录中,并且仍然链接到代码的中心目录时,您也可以使用相对代码表链接。例如,一个兄弟目录可以称为“code-tables”,并且可以将 src="MyCode.xml" 语句修改为 src="../code-tables/MyCode.xml"。

如果您有表单的 XML Schema,您还可以提取每个 simpleType 的所有枚举列表。然后,可以将此代码列表传递给创建一个注册表中所有代码列表的网络服务。这允许在 XML Schema 中添加新代码时自动更新表单。

如果您有一个包含所有表单代码的 RESTful 网络服务,您可以用该网络服务的 URI 替换此 XML 文件。

下一页: 选择日期 | 上一页: 从模型中选择
首页: XForms
华夏公益教科书