您好,登錄后才能下訂單哦!
小編給大家分享一下在XML模式中擴展枚舉列表的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
在列表中添加新值是一種常見而且必要的需求。模式設計者通常希望在系統架構中構建一種添加附加值的方法,并且該附加值在設計階段是未知的。模式設計者如何創建一個可擴展、易于實現的枚舉值列表?本文將介紹幾種實現這一目標的方法。
模式設計者和實現人員需要一種擴
在列表中添加新值是一種常見而且必要的需求。模式設計者通常希望在系統架構中構建一種添加附加值的方法,并且該附加值在設計階段是未知的。模式設計者如何創建一個可擴展、易于實現的枚舉值列表?本文將介紹幾種實現這一目標的方法。
模式設計者和實現人員需要一種擴展 XML 模式中現有枚舉列表的方法。不幸的是,XML 模式規范不允許在這些列表的創建過程中(參閱 參考資料)進行擴展。設計階段所選的值是固定的,而且都是可用的。盡管有這樣的限制,人們仍使用各種替代方案來實現列表擴展。很多使用現有的不能改變的模式的客戶經常提出這一要求。他們希望在添加新功能的同時保持向后兼容性。本文中,您將會看到模式設計者如何克服障礙實現該功能。
枚舉列表 是特定數據點的一組指定值。例如,您也許通過固定的值列表查看國家代碼,包括 DE(德國)、US(美國)和 JP(日本)。根據給定的值集,當一個新國家被識別出時,如 TL(東帝汶)或者 BA(波斯尼亞及黑塞哥維那),該怎么辦?使用以前的名稱列表的客戶必須改變實現來容納新值。
當使用 XML 模式對數據建模時,枚舉值被顯式列出。因此,國家代碼列表依次包含各個枚舉值。經常需要識別列表中的新值,而且必須將其容納到列表中,模式設計者試圖找到一種擴展列表的方法,實際上,是將這種方法構建到設計中,允許添加在設計時未知的附加值。
創建可擴展的枚舉列表
在尋找這一問題的解決方案時,受到四個關鍵標準的影響:
首先,要在設計階段之后擴展列表。不管是快速建立一個新的貿易伙伴還是建立時間關鍵型的新數據字段,在關鍵時刻進行擴展是一項實際需求。
其次,能夠在解析器中驗證值對于簡化實現是非常關鍵的。
第三,在單個周期內完成解析和驗證是至關重要的。這就避免了像 Genericode 解決方案一樣,在一個單獨的周期和解析器中進行驗證。對于某些設置來說,添加新技術需求會導致成本太高或者太耗時。
最后,解決方案必須能夠向后兼容原始的模式。不兼容的列表更改不能稱為擴展。
有些人認為根本就不應該擴展枚舉列表。數據建模人員也許認為如果想讓模型包含更多數據、擴展模型,那么可以根據產品創建模式 — 實際上,在需要時創建更大的模型并減少限制。如果能夠控制原始模式和數據模型,這樣做是可以的,這種方法也許是理想的方法。但是,如果您需要在設計階段之后進行實際擴展,這樣的方法是行不通的。
還有人認為擴展枚舉列表的關鍵是不使用 XML 模式驗證解析器。Genericode(參閱 參考資料)建議在第二層對枚舉列表進行驗證,脫離初始的 XML 模式解析器驗證過程。這種理論是正確的,而且這種方法的應用會越來越廣泛。但是,如果要在一個解析周期內完成,這種解決方案是無法做到的。在某些情況下,不可能執行第二個驗證周期。
當然,您可以在新列表中創建新元素。但是,不能向后兼容原始模式。我們的目標是在保持向后兼容性的同時實現一個可擴展的列表(參閱 參考資料)。
對于本文的目標,這里作出的假設基于我與客戶打交道的經驗 —— 即用附加值擴展現有枚舉列表的需求。另外,我假設在一個步驟內完成 XML 模式解析與驗證等操作。
擴展枚舉列表的必要條件
該擴展示例有四個必要條件:
允許在設計階段之后擴展枚舉列表。
用解析器驗證枚舉列表。
在一個周期內驗證枚舉列表。
維持和原始模式的向后兼容性。
舉例來說,一個團隊需要處理一個區域產業協會的枚舉列表(或任意現有列表)為例,并根據使用修改模式組件。先前的模式提供 MaritalStatus 組件和值的枚舉列表,如 清單 1 所示。
清單 1. 婚姻狀況枚舉列表
<xsd:simpleType name="MaritalStatusEnumType"> <xsd:restriction base="xsd:normalizedString"> <xsd:enumeration value="porced"/> <xsd:enumeration value="Married"/> <xsd:enumeration value="NeverMarried"/> <xsd:enumeration value="Separated"/> <xsd:enumeration value="SignificantOther"/> <xsd:enumeration value="Widowed"/> <xsd:enumeration value="Unknown"/> </xsd:restriction> </xsd:simpleType> <xsd:element name="MaritalStatus" type="MaritalStatusEnumType"/>
假設一個公司要使用這些值,另外,還要支持它的重要貿易伙伴使用另一個值。CivilUnion 是一個擴展值,公司識別出該值不屬于原始模式。但是從語義上來說,使用現有元素 —MaritalStatus — 也是可以的。公司要如何實現呢?
回頁首
解決方案 1: 編輯原始模式使其包含新枚舉值
當然,編輯原始模式使其包含新枚舉值是最直接的方法。保留模式的本地副本,然后編輯這些模式以支持公司使用的枚舉值。
優點:易于實現
缺點:
需要編輯原始模式,這些模式將逐漸改變,以至于無法控制。如果擴展一個先前存在的列表,那么創建者(貿易伙伴、協會等)可能要發布列表的新版本。您需要將編輯的內容傳播到每個新版本中。
手動編輯模式會導致意外的編輯錯誤。
如果您不能(或不想)編輯原始模式,則需要一種替代方法。
回頁首
解決方案 2: 創建新枚舉列表并加入到原始列表中
第二個選擇是創建新枚舉列表,并將其加入到原始枚舉列表中。清單 1 顯示原始婚姻狀況列表。清單 2 顯示最新創建的枚舉列表。
清單 2. 新婚姻狀況枚舉列表
<xsd:simpleType name="MyExtMaritalStatusEnumType"> <xsd:restriction base="xsd:normalizedString"> <xsd:enumeration value="CivilUnion"/> </xsd:restriction> </xsd:simpleType>
使用 <xsd:union> 標記將其與原始列表結合,如 清單 3 所示。
清單 3. 將兩個列表組合起來
<xsd:simpleType name="MaritalStatusType_Union"> <xsd:union memberTypes="MyExtMaritalStatusEnumType MaritalStatusEnumType"/> </xsd:simpleType> <xsd:element name="MaritalStatus" type="MaritalStatusType_Union"/>
該解決方案仍然需要對模式進行編輯 — 即將元素 MaritalStatus 由 MaritalStatusType 類型轉換為 MaritalStatusType_Union 類型。改動不大,但仍然有一些手動編輯工作。
優點:不改變原始枚舉列表。
缺點:
在設計階段所有的值必須是已知的,防止后期綁定解決方案。
需要 <xsd:union> 標記支持,但有時該標記無法用工具實現。
回頁首
解決方案 3: 創建一個模式,并與原始枚舉類型結合
現在看一下有關眼睛顏色的人口數據用例。清單 4 顯示這一列表。
清單 4. Person Eye Color 枚舉列表
<xsd:simpleType name="PersonEyeColorType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="Black"/> <xsd:enumeration value="Hazel"/> <xsd:enumeration value="Gray"/> <xsd:enumeration value="Brown"/> <xsd:enumeration value="Violet"/> <xsd:enumeration value="Green"/> <xsd:enumeration value="Blue"/> <xsd:enumeration value="Maroon"/> <xsd:enumeration value="Pink"/> <xsd:enumeration value="Dichromatic"/> <xsd:enumeration value="Unknown"/> </xsd:restriction> </xsd:simpleType>
接下來,創建采用新值的模式(一個正則表達式)。該模式是以 x: 為前綴的任意字符串。x: 是標準枚舉列表和擴展列表之間的描繪程序。清單 5 顯示這一模式。
清單 5. 用于擴展的正則表達式
<xsd:simpleType name="StringPatternType"> <xsd:restriction base="xsd:string"> <xsd:pattern value="x:\S.*"/> </xsd:restriction> </xsd:simpleType>
最后,使用 <xsd:union> 標記結合列表與模式,如 清單 6 所示。
清單 6. 枚舉列表與擴展模式的結合
<xsd:simpleType name="MyExtPersonEyeColorType"> <xsd:union memberTypes="PersonEyeColorType StringPatternType"/> </xsd:simpleType> <xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>
同一節點擁有標準和擴展值。兩個值很容易分離,而且都可以用解析器驗證,如 清單 7 所示。
清單 7. XML 實例樣例
<PersonEyeColor>Black</PersonEyeColor> <PersonEyeColor>x:Teal</PersonEyeColor>
優點:
同一元素可用于所有數據。
用解析器對基本枚舉列表進行驗證。
清晰地分隔擴展值。
該解決方案允許在以后綁定新值。
缺點:
必須解析元素的內容,以確定是否已經被擴展。
模式解析器必須支持正則表達式。
需要 <xsd:union> 標記支持。
回頁首
解決方案 4:使用單獨的字段用于擴展
在該解決方案中,枚舉字段不會變化。然而,您要在模式中設計一個擴展字段來容納附加值。在本例中,初始列表是依賴型的(就業受益者和受養人之間的關系),如 清單 8 所示。
清單 8. 依賴關系枚舉列表
<xsd:simpleType name="DependentRelationshipEnumType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="AdoptedChild"/> <xsd:enumeration value="Brother"/> <xsd:enumeration value="Child"/> <xsd:enumeration value="ExSpouse"/> <xsd:enumeration value="Father"/> <xsd:enumeration value="Granddaughter"/> <xsd:enumeration value="Grandson"/> <xsd:enumeration value="Grandfather"/> <xsd:enumeration value="Grandmother"/> <xsd:enumeration value="LifePartner"/> <xsd:enumeration value="Mother"/> <xsd:enumeration value="Sister"/> <xsd:enumeration value="Spouse"/> <xsd:enumeration value="Extension"/> </xsd:restriction> </xsd:simpleType>
需要一個能夠容納新值的附加屬性 — extension—。清單 9 顯示了該屬性。
清單 9. 依賴關系的 extension 屬性
<xsd:complexType name="DependentRelationshipType"> <xsd:simpleContent> <xsd:extension base="DependentRelationshipEnumType"> <xsd:attribute name="extension" type="xsd:string"/> </xsd:extension> </xsd:simpleContent> </xsd:complexType> <xsd:element name="DependentRelationship" type="DependentRelationshipType"/>
清單 10 顯示一些反映 extension 的 XML 實例。
清單 10. 示例 XML 實例
<DependentRelationship>Child</DependentRelationship> <DependentRelationship extension="MyNewRelationship">Extension</DependentRelationship>
優點:
不需要編輯原始模式。
該解決方案允許在以后綁定新值。
在原始模式中顯式設計 extension 方法。
缺點:
在設計階段,必須在每個枚舉列表中設計 extension 方法。
必須在元素中而不是在屬性中設置枚舉值。
回頁首
解決方案 5: 基于文檔的方法 —— 與字符串結合
注意:解決方案 5 和解決方案 6 違反了在一個周期內進行驗證 這一要求。但是,我之所以在這里介紹它們,是因為在很多實際環境中可以使用這些方法。
在第 5 個解決方案中,使用 <xsd:union> 標記將枚舉列表與字符串結合。實際上,該解決方案提示接收系統哪些值是標準的(包括包裝和拼寫)。但實際上字符串字段可以存放任何值。因此,解析器并不驗證值。相反,這些值在第二個周期或者在接收數據的應用程序中驗證。有些 XML 組織就使用這樣的方案。
清單 11 顯示通過 <xsd:union> 將一個枚舉列表和 <xsd:string> 結合。因為任意值都可以是一個字符串,所以不用驗證枚舉列表。這些值建議使用標準值。
清單 11. 與字符串結合的 DayOfWeek 枚舉列表
<xsd:simpleType name="DayOfWeekEnumType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="Sunday"/> <xsd:enumeration value="Monday"/> <xsd:enumeration value="Tuesday"/> <xsd:enumeration value="Wednesday"/> <xsd:enumeration value="Thursday"/> <xsd:enumeration value="Friday"/> <xsd:enumeration value="Saturday"/> </xsd:restriction> </xsd:simpleType> <xsd:element name="DayOfWeek" type="DayOfWeekEnumType"/> <xsd:simpleType name="ExtendedDayOfWeekType"> <xsd:union memberTypes="DayOfWeekEnumType xsd:string"/> </xsd:simpleType> <xsd:element name="DayOfWeek_solution5" type="ExtendedDayOfWeekType"/>
優點:可以添加任意的擴展值,即使在后期綁定時也可以添加。
缺點:
解析器不驗證枚舉值,在第二個步驟中才進行驗證。
需要 <xsd:union> 標記支持。
回頁首
解決方案 6: 基于文檔的方法 —— 使用 <xsd:annotation>
要使用該方法,將實際的枚舉值放到 <xsd:documentation> 標記內,同時將數據字段保留為一個簡單字符串。清單 12 顯示枚舉值。
清單 12. 在 <xsd:documentation> 標記內的枚舉值
<xsd:element name="DayOfWeek" type="xsd:string"> <xsd:annotation> <xsd:documentation> <!-- suggested enumerations --> <xsd:enumeration value="Sunday"/> <xsd:enumeration value="Monday"/> <xsd:enumeration value="Tuesday"/> <xsd:enumeration value="Wednesday"/> <xsd:enumeration value="Thursday"/> <xsd:enumeration value="Friday"/> <xsd:enumeration value="Saturday"/> </xsd:documentation> </xsd:annotation> </xsd:element>
優點:
可以添加任意的擴展值,即使在后期綁定時也可以添加。
只需要最簡單的 XML 模式特性。
缺點:解析器不驗證枚舉值。
回頁首
未討論的方法
我省略了其他幾種擴展枚舉列表的解決方案。下面簡單介紹了兩種沒有使用的方法:
使用 <xsd:redefine> 標記: 通常不使用 XML 模式的這一特性,而且一般無法用工具實現它。該方法經常被認為是避免重新定義的最佳實踐。
使用 substitutionGroup 元素替換包含所有值的聯合列表: 另外一種出色的解決方案,使用了替換組和聯合。將原始列表與新列表聯合以創建一個完整的枚舉列表,然后使用 substitutionGroups 標記(或 <xsi:type> 標記)替換一個全局作用域元素。該方法的缺點是替換不能派生有效的聯合,替換需要兩個組件來自相同的基類型。擴展和限制是替換的兩個有效方法。但是,根據 XML 模式規范,聯合并不是有效的派生技術(參閱 參考資料)。
回頁首
結束語
XML 模式設計者和實現人員需要一種方法來擴展現有的枚舉列表。因為一旦原始列表創建后,規范不允許進行擴展,因此需要找到一種方法實際實現擴展。實現人員可以使用本文的示例來設計和擴展枚舉列表。每種方法都有優缺點,沒有一種方法在所有用例中都是最佳方法。那么,應該使用哪種方法呢?
請考慮這些經驗法則:
如果您習慣編輯原始枚舉列表或模式,而且在設計階段就知道所有要擴展的枚舉值,最好使用 解決方案 1(手動編輯原始列表)或 解決方案 2(創建新列表并加入到原始列表中)。
如果想使用相同的語義元素來包含基本枚舉列表和擴展枚舉列表,可以考慮 解決方案 3(與模式聯合)。
如果允許原始列表與擴展列表有不同的字段,可以使用 解決方案 4(獨立的字段)。
如果不想在解析器中解析枚舉值,可以考慮 Genericode 方法或使用 解決方案 5 或 解決方案 6。
這些指導原則可以使模式設計者找到實用的最佳實踐,而且可以幫助他們創建易于實現、可擴展的枚舉列表。
XML 模式和 XML 實例示例 ExtendEnumeratedListsCode.zip 2KB
以上是“在XML模式中擴展枚舉列表的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。