跳转到内容

XForms/从文件选择代码

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

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

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

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

[编辑 | 编辑源代码]

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

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

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

从 Web 服务加载代码

[编辑 | 编辑源代码]

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

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

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

[编辑 | 编辑源代码]

将单个代码表加载到单个实例中的问题是,您必须对每个代码表执行单独的 HTTP GET 操作。对于只有一个或两个小选择列表的表单来说,这不是问题。但是,对于具有许多选择列表的大型表单,这会减慢表单响应时间。解决方案是通过单个 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 Web 服务提取数据

[编辑 | 编辑源代码]

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

<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

[编辑 | 编辑源代码]

将数据加载到模型后,每个 **select1** 或 **select** 控件都可以使用 **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. 将所有标签/值对存储在外部代码表文件中,或从 Web 服务获取此信息。
  2. 对于每个表单,创建一个 Web 服务,该服务将为该表单中使用的所有代码生成一个 code-tables 元素。
  3. 将 code-tables 元素加载到模型中的单独实例中,其 id 为“code-tables”。
  4. 对于每个 select1 或 select 元素,通过获取具有该名称的代码表,从该实例中选择代码表。

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

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

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

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