XForms/從檔案選擇程式碼

設計表單的人員經常需要維護許多程式碼表。這些程式碼表可能會頻繁更改,並且可能存在更新集中維護的程式碼表資料庫的流程。因此,您希望每個表單都能動態地從 XML 檔案或 RESTful Web 服務獲取當前的相關程式碼。
此示例程式演示瞭如何直接從檔案或程式碼表 Web 服務讀取帶有標籤的程式碼列表。在此示例中,包含程式碼的檔案只是一個格式良好的 XML 檔案,位於與表單相同的目錄中。
以下程式碼片段通常位於 HTML 頭部,演示瞭如何透過使用例項的“src”屬性從與表單相同的目錄中的本地檔案讀取 XML 資料。
<html>
<xf:model>
<xf:instance src="XMLSchemaTypeCode.xml" id="XMLSchemaTypeCode"/>
</xf:model>
</html>
通常會有一個單個 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 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 檔案 **必須** 包含一個根資料元素,該元素必須與節點集引數匹配。
您可以將例項 **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** 或 **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 不包含用於表示的資訊,因此我們使用以下工作流作為“最佳實踐”。
- 將所有標籤/值對儲存在外部程式碼表檔案中,或從 Web 服務獲取此資訊。
- 對於每個表單,建立一個 Web 服務,該服務將為該表單中使用的所有程式碼生成一個 code-tables 元素。
- 將 code-tables 元素載入到模型中的單獨例項中,其 id 為“code-tables”。
- 對於每個 select1 或 select 元素,透過獲取具有該名稱的程式碼表,從該例項中選擇程式碼表。
當一組共享通用程式碼的複雜表單需要放置在它們自己的目錄中,但仍然需要連結到程式碼的中央目錄時,您也可以使用相對程式碼表連結。例如,一個兄弟目錄可以稱為“code-tables”,並且 src="MyCode.xml" 語句可以修改為 src="../code-tables/MyCode.xml"。
如果您有表單的 XML 模式,您還可以提取每個 simpleType 的所有列舉列表。然後,此程式碼列表可以傳遞給一個 Web 服務,該服務會建立登錄檔中所有程式碼的列表。這允許表單在 XML 模式中新增新程式碼時自動更新。
如果您有一個包含表單所有程式碼的 RESTful Web 服務,您可以用這個 Web 服務 URI 替換 XML 檔案。