XMLスキーマにおける列挙リストの拡張
2022-01-25 16:31:46
リストに新しい値を追加することは、一般的かつ必要な要件です。スキーマ設計者はしばしば、設計段階では未知の値を追加する方法をシステム・アーキテクチャに組み込みたいと考える。パターン設計者は、拡張性があり、実装が簡単な値の列挙リストをどのように作成すればよいのでしょうか。この記事では、この目標を達成するためのいくつかの方法について説明する。
スキーマ設計者や実装者は、XMLスキーマに含まれる既存の列挙リストを拡張する方法を必要としています。残念ながら、XML スキーマの仕様では、これらのリストの作成中に拡張を行うことはできません(参考文献を参照)。設計段階で選択された値は固定されており、すべて利用可能である。この制限にもかかわらず、リストの拡張を実装するために、さまざまな代替手段が用いられてきました。これは、変更できない既存のスキーマを使用している多くのお客様から、しばしば要望されることです。彼らは、後方互換性を維持しながら、新しい機能を追加したいと考えています。この記事では、パターン設計者がこの機能を実現するために、どのように障害を克服することができるかを見ていきます。
列挙リストとは、特定のデータポイントに対して指定された値の集合のことである。たとえば、DE(ドイツ)、US(米国)、JP(日本)など、固定された値のリストを通して国コードを見ることができます。TL(東ティモール)やBA(ボスニア・ヘルツェゴビナ)のように、与えられた値群に基づいて新しい国を識別する場合はどうなるのでしょうか。以前の名前のリストを使用しているお客様は、新しい値に対応するために実装を変更する必要があります。
XML スキーマを使用してデータをモデル化する場合、列挙された値は明示的にリストアップされます。したがって、国コードのリストには、個々の列挙された値が順番に含まれています。しばしば、リスト内の新しい値を特定する必要があり、リストに収容しなければなりません。スキーマ設計者は、リストを拡張する方法を見つけようとし、事実上、これを設計に組み込み、設計時には不明だった値を追加できるようにします。
拡張可能な列挙型リストの作成
この問題の解決策を探すには、4つの重要な基準が影響しました。
まず、設計段階から対象を広げること。新しい取引先を素早く作成したり、タイムクリティカルな新しいデータフィールドを作成したり、重要なタイミングでのスケーリングは本当に必要なことなのです。
次に、パーサーで値を検証できることは、実装を簡素化する上で非常に重要です。
第三に、解析と検証を1つのサイクルで行うことが重要である。これにより、Genericodeソリューションのように、別のサイクルとパーサーで検証する必要性を回避することができます。セットアップによっては、新しい技術要件を追加することは、コストや時間がかかりすぎる場合があります。
最後に、ソリューションは元のスキーマとの後方互換性を確保できなければなりません。互換性のないリストの変更は、拡張機能とは呼べません。
列挙型リストは一切拡張すべきではないという考え方もある。データモデラーは、モデルに多くのデータを含ませて拡張したいのであれば、製品をベースにスキーマを作ればよい、つまり、事実上、より大きなモデルを作り、必要に応じて制約を減らせばよいと考えるかもしれません。元のスキーマとデータモデルを制御できるのであれば、この方法は問題ありませんし、この方法は理想的かもしれません。しかし、設計段階を越えて実際に拡張する必要がある場合、このようなアプローチはうまくいきません。
Genericode(参考文献参照)は、列挙リストを最初のXMLスキーマパーサーの検証プロセスから離れた第二のレベルで検証することを提案している。この理論は正しく、この方法はますます広く使われるようになるだろう。しかし、1回のパーシングサイクルで行わなければならない場合、この解決策は不可能である。場合によっては、2回目の検証サイクルを実行することができないこともある。
もちろん、新しい要素を新しいリストで作成することもできます。しかし、元のスキーマとの後方互換性はありません。目標は、後方互換性を維持しつつ、拡張可能なリストを実装することです(参考文献参照)。
この記事の目的上、ここでの仮定は、私が顧客と取引した経験に基づくものである -- すなわち、既存の列挙リストを追加値で拡張する必要性があることだ。また、XMLスキーマのパースや検証などは1ステップで行われるものと仮定しています。
列挙リストの拡張に必要な条件
拡張の例では、4つの必要条件があります。
設計段階以降に列挙リストを拡張できるようにする。
パーサーで列挙リストを検証する。
列挙リストの検証を1サイクルで行う。
オリジナルスキーマとの後方互換性を維持する。
例えば、あるチームが、地域の業界団体の列挙リスト(あるいは既存のリスト)を扱い、使用状況に応じてスキーマのコンポーネントを修正する必要があるとする。以前のスキーマでは、リスト 1 に示すように MaritalStatus コンポーネントと値の列挙リストが用意されていました。
リスト1. 配偶者の有無の列挙リスト
<xsd:simpleType name="MaritalStatusEnumType">
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="Divorced"/>
<xsd:enumeration value="既婚者"/>
<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:新しい列挙リストを作成し、それを元のリストに追加する
2つ目の方法は、新しい列挙リストを作成し、それを元の列挙リストに追加する方法である。リスト1は、オリジナルの婚姻状況リストです。リスト2は最近作成された列挙リストを示しています。
リスト2. 新しい婚姻状況列挙リスト
<xsd:simpleType name="MyExtMaritalStatusEnumType">
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="CivilUnion"/>
</xsd:restriction>
</xsd:simpleType>
リスト3のように、<xsd:union>タグを使って、元のリストと結合します。
リスト3. 2つのリストを結合する
<xsd:simpleType name="MaritalStatusType_Union">
<xsd:union memberTypes="MyExtMaritalStatusEnumType MaritalStatusEnumType"/>
</xsd:simpleType>
<xsd:element name="MaritalStatus" type="MaritalStatusType_Union"/>
つまり、MaritalStatus 要素を MaritalStatusType 型から MaritalStatusType_Union 型に変換する必要があります。この変更は重要ではありませんが、手動で編集する必要があります。
メリット:元のenumリストに変更がない。
デメリット
設計段階ですべての値を把握する必要があり、後々の解の拘束を防ぐことができる。
xsd:union>マークアップのサポートが必要ですが、このマークアップはツールで実装できない場合があります。
このページの先頭へ戻る
解決策3:スキーマを作成し、元のenum型と結合する
次に、目の色に関する人口統計データのユースケースを見てみましょう。リスト 4 は、このリストを示しています。
リスト4. 人の目の色の列挙のリスト
<xsd:simpleType name="PersonEyeColorType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ブラック"/>
<xsd:enumeration value="Hazel"/>
<xsd:enumeration value="Gray"/>
<xsd:enumeration value="Brown"/>
<xsd:enumeration value="Violet"/>
<xsd:enumeration value="Green"/>
<xsd:enumeration value="ブルー"/>
<xsd:enumeration value="Maroon"/>
<xsd:enumeration value="ピンク"/>
<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>
最後に、リスト6に示すように、リストとスキーマを結合するために <xsd:union> タグを使用します。
リスト6. 列挙型リストと拡張スキーマを結合する
<xsd:simpleType name="MyExtPersonEyeColorType">
<xsd:union memberTypes="PersonEyeColorType StringPatternType"/>
</xsd:simpleType>
<xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>.Xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>
同じノードに標準値と拡張値の両方が存在する。リスト 7 に示すように、2 つの値は簡単に分離でき、パーサーで両方を検証することができます。
リスト7. サンプル XML インスタンス
<PersonEyeColor>Black</PersonEyeColor>
<PersonEyeColor>x:Teal</PersonEyeColor>
長所
すべてのデータに同じ要素を使用することができます。
基本列挙リストをパーサーで検証する。
拡張値を明確に分離する。
この解決策では、新しい値を後でバインドすることができます。
デメリット
要素の内容を解析して、展開されているかどうかを判断する必要があります。
スキーマパーサーは正規表現をサポートする必要があります。
xsd:union>タグのサポートが必要です。
このページの先頭へ戻る
解決策4:拡張機能用に別のフィールドを使用する
この解決策では、列挙されたフィールドは変更されない。しかし、追加された値を保持するために、スキーマに拡張フィールドを設計したい。この例では、リスト 8 に示すように、初期リストは依存関係 (雇用の受益者と扶養家族の関係) になっています。
リスト8. 依存関係列挙リスト
スキーマ設計者や実装者は、XMLスキーマに含まれる既存の列挙リストを拡張する方法を必要としています。残念ながら、XML スキーマの仕様では、これらのリストの作成中に拡張を行うことはできません(参考文献を参照)。設計段階で選択された値は固定されており、すべて利用可能である。この制限にもかかわらず、リストの拡張を実装するために、さまざまな代替手段が用いられてきました。これは、変更できない既存のスキーマを使用している多くのお客様から、しばしば要望されることです。彼らは、後方互換性を維持しながら、新しい機能を追加したいと考えています。この記事では、パターン設計者がこの機能を実現するために、どのように障害を克服することができるかを見ていきます。
列挙リストとは、特定のデータポイントに対して指定された値の集合のことである。たとえば、DE(ドイツ)、US(米国)、JP(日本)など、固定された値のリストを通して国コードを見ることができます。TL(東ティモール)やBA(ボスニア・ヘルツェゴビナ)のように、与えられた値群に基づいて新しい国を識別する場合はどうなるのでしょうか。以前の名前のリストを使用しているお客様は、新しい値に対応するために実装を変更する必要があります。
XML スキーマを使用してデータをモデル化する場合、列挙された値は明示的にリストアップされます。したがって、国コードのリストには、個々の列挙された値が順番に含まれています。しばしば、リスト内の新しい値を特定する必要があり、リストに収容しなければなりません。スキーマ設計者は、リストを拡張する方法を見つけようとし、事実上、これを設計に組み込み、設計時には不明だった値を追加できるようにします。
拡張可能な列挙型リストの作成
この問題の解決策を探すには、4つの重要な基準が影響しました。
まず、設計段階から対象を広げること。新しい取引先を素早く作成したり、タイムクリティカルな新しいデータフィールドを作成したり、重要なタイミングでのスケーリングは本当に必要なことなのです。
次に、パーサーで値を検証できることは、実装を簡素化する上で非常に重要です。
第三に、解析と検証を1つのサイクルで行うことが重要である。これにより、Genericodeソリューションのように、別のサイクルとパーサーで検証する必要性を回避することができます。セットアップによっては、新しい技術要件を追加することは、コストや時間がかかりすぎる場合があります。
最後に、ソリューションは元のスキーマとの後方互換性を確保できなければなりません。互換性のないリストの変更は、拡張機能とは呼べません。
列挙型リストは一切拡張すべきではないという考え方もある。データモデラーは、モデルに多くのデータを含ませて拡張したいのであれば、製品をベースにスキーマを作ればよい、つまり、事実上、より大きなモデルを作り、必要に応じて制約を減らせばよいと考えるかもしれません。元のスキーマとデータモデルを制御できるのであれば、この方法は問題ありませんし、この方法は理想的かもしれません。しかし、設計段階を越えて実際に拡張する必要がある場合、このようなアプローチはうまくいきません。
Genericode(参考文献参照)は、列挙リストを最初のXMLスキーマパーサーの検証プロセスから離れた第二のレベルで検証することを提案している。この理論は正しく、この方法はますます広く使われるようになるだろう。しかし、1回のパーシングサイクルで行わなければならない場合、この解決策は不可能である。場合によっては、2回目の検証サイクルを実行することができないこともある。
もちろん、新しい要素を新しいリストで作成することもできます。しかし、元のスキーマとの後方互換性はありません。目標は、後方互換性を維持しつつ、拡張可能なリストを実装することです(参考文献参照)。
この記事の目的上、ここでの仮定は、私が顧客と取引した経験に基づくものである -- すなわち、既存の列挙リストを追加値で拡張する必要性があることだ。また、XMLスキーマのパースや検証などは1ステップで行われるものと仮定しています。
列挙リストの拡張に必要な条件
拡張の例では、4つの必要条件があります。
設計段階以降に列挙リストを拡張できるようにする。
パーサーで列挙リストを検証する。
列挙リストの検証を1サイクルで行う。
オリジナルスキーマとの後方互換性を維持する。
例えば、あるチームが、地域の業界団体の列挙リスト(あるいは既存のリスト)を扱い、使用状況に応じてスキーマのコンポーネントを修正する必要があるとする。以前のスキーマでは、リスト 1 に示すように MaritalStatus コンポーネントと値の列挙リストが用意されていました。
リスト1. 配偶者の有無の列挙リスト
<xsd:simpleType name="MaritalStatusEnumType">
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="Divorced"/>
<xsd:enumeration value="既婚者"/>
<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:新しい列挙リストを作成し、それを元のリストに追加する
2つ目の方法は、新しい列挙リストを作成し、それを元の列挙リストに追加する方法である。リスト1は、オリジナルの婚姻状況リストです。リスト2は最近作成された列挙リストを示しています。
リスト2. 新しい婚姻状況列挙リスト
<xsd:simpleType name="MyExtMaritalStatusEnumType">
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="CivilUnion"/>
</xsd:restriction>
</xsd:simpleType>
リスト3のように、<xsd:union>タグを使って、元のリストと結合します。
リスト3. 2つのリストを結合する
<xsd:simpleType name="MaritalStatusType_Union">
<xsd:union memberTypes="MyExtMaritalStatusEnumType MaritalStatusEnumType"/>
</xsd:simpleType>
<xsd:element name="MaritalStatus" type="MaritalStatusType_Union"/>
つまり、MaritalStatus 要素を MaritalStatusType 型から MaritalStatusType_Union 型に変換する必要があります。この変更は重要ではありませんが、手動で編集する必要があります。
メリット:元のenumリストに変更がない。
デメリット
設計段階ですべての値を把握する必要があり、後々の解の拘束を防ぐことができる。
xsd:union>マークアップのサポートが必要ですが、このマークアップはツールで実装できない場合があります。
このページの先頭へ戻る
解決策3:スキーマを作成し、元のenum型と結合する
次に、目の色に関する人口統計データのユースケースを見てみましょう。リスト 4 は、このリストを示しています。
リスト4. 人の目の色の列挙のリスト
<xsd:simpleType name="PersonEyeColorType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ブラック"/>
<xsd:enumeration value="Hazel"/>
<xsd:enumeration value="Gray"/>
<xsd:enumeration value="Brown"/>
<xsd:enumeration value="Violet"/>
<xsd:enumeration value="Green"/>
<xsd:enumeration value="ブルー"/>
<xsd:enumeration value="Maroon"/>
<xsd:enumeration value="ピンク"/>
<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>
最後に、リスト6に示すように、リストとスキーマを結合するために <xsd:union> タグを使用します。
リスト6. 列挙型リストと拡張スキーマを結合する
<xsd:simpleType name="MyExtPersonEyeColorType">
<xsd:union memberTypes="PersonEyeColorType StringPatternType"/>
</xsd:simpleType>
<xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>.Xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>
同じノードに標準値と拡張値の両方が存在する。リスト 7 に示すように、2 つの値は簡単に分離でき、パーサーで両方を検証することができます。
リスト7. サンプル XML インスタンス
<PersonEyeColor>Black</PersonEyeColor>
<PersonEyeColor>x:Teal</PersonEyeColor>
長所
すべてのデータに同じ要素を使用することができます。
基本列挙リストをパーサーで検証する。
拡張値を明確に分離する。
この解決策では、新しい値を後でバインドすることができます。
デメリット
要素の内容を解析して、展開されているかどうかを判断する必要があります。
スキーマパーサーは正規表現をサポートする必要があります。
xsd:union>タグのサポートが必要です。
このページの先頭へ戻る
解決策4:拡張機能用に別のフィールドを使用する
この解決策では、列挙されたフィールドは変更されない。しかし、追加された値を保持するために、スキーマに拡張フィールドを設計したい。この例では、リスト 8 に示すように、初期リストは依存関係 (雇用の受益者と扶養家族の関係) になっています。
リスト8. 依存関係列挙リスト
関連
-
WAPチュートリアル(9):WMLの例 - XML/XSLT
-
WAPチュートリアル(4):WMLのリンクと画像 - XML/XSLT
-
XML基本概念入門ラーニングガイド
-
WAPチュートリアル(4):WMLのリンクと画像 - XML/XSLT
-
WAPチュートリアル(11):WAPフォーラムとオープンモバイルアライアンス・フォーラム - XML/XSLT
-
(javascript+asp)XML、XSL変換出力HTML
-
XMLにおけるDTD文書型定義の徹底分析
-
XMLマークアップ言語の基本概念と構文のチュートリアル
-
WEBページツール言語XMLの理解(VI) Outlook
-
XML Resolution:XMLアプリケーションノート
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
WAPチュートリアル(3):WMLの書式設定 - XML/XSLT
-
XMLの処理命令について簡単に説明します。
-
WAPチュートリアル(2):WAPの基本 - XML/XSLT
-
WAPチュートリアル(11):WAPフォーラムとオープンモバイルアライアンス・フォーラム - XML/XSLT
-
XMLチュートリアル。要素の宣言 - XML/XSLT
-
XML義姉妹″Textiles:Dublin Core
-
XMLにおけるドキュメントと宣言の使い分けを解説
-
javascriptでxmlを操作するための方法と技術
-
C#によるxmlファイルの読み書きのアプリケーション
-
XML義姉妹:FIXMLディアボリックVG