新しい値をリストに追加することは一般的かつ必要な要件です。パターン設計者は、付加価値を追加する方法をシステムアーキテクチャに組み込むことがよくありますが、その付加価値は設計段階ではわかりません。スキーマ設計者は、拡張可能で実装が簡単な列挙値のリストをどのように作成できるでしょうか?この記事では、この目標を達成するためのいくつかの方法を紹介します。
パターン設計者と実装者には拡張機能が必要です
リストに新しい値を追加することは一般的であり、必要な要件です。パターン設計者は多くの場合、付加価値を追加する方法をシステム アーキテクチャに組み込む必要がありますが、その付加価値は設計段階ではわかりません。スキーマ設計者は、拡張可能で実装が簡単な列挙値のリストをどのように作成できるでしょうか?この記事では、この目標を達成するためのいくつかの方法を紹介します。
スキーマの設計者と実装者は、XML スキーマ内の既存の列挙リストを拡張する方法を必要としています。残念ながら、XML スキーマ仕様では、これらのリストの作成中に拡張することはできません (「参考文献」を参照)。設計段階で選択された値は固定されており、使用可能です。この制限にもかかわらず、人々は依然としてリストを拡張するためにさまざまな代替手段を使用しています。これは、変更できない既存のスキーマを使用している顧客からよく要求されます。彼らは、新機能を追加しながら、下位互換性を維持したいと考えています。この記事では、パターン設計者がこの機能を実現するためにどのように障害を克服したかを説明します。
列挙リストは、特定のデータポイントに対して指定された値のセットです。たとえば、DE (ドイツ)、US (米国)、JP (日本) などの固定値リストを通じて国コードを表示できます。与えられた一連の価値観が与えられた場合、TL (東ティモール) や BA (ボスニア ヘルツェゴビナ) などの新しい国が特定された場合、何をすべきでしょうか?以前の名前リストを使用しているクライアントは、新しい値に対応するために実装を変更する必要があります。
XML スキーマを使用してデータをモデル化する場合、列挙値は明示的にリストされます。したがって、国コードのリストには、各列挙値が順番に含まれます。多くの場合、リスト内の新しい値を特定してリストに組み込む必要があり、パターン設計者はリストを拡張する方法を見つけようとし、実際にはこれをデザインに組み込んで新しい値を追加できるようにします。設計時には不明な付加価値。
拡張可能な列挙リストを作成する
この問題の解決策を探しているとき、私たちは 4 つの重要な基準に影響を受けました。
まず、設計段階の後にリストを拡張します。新しい取引パートナーを迅速に確立する場合でも、タイム クリティカルな新しいデータ フィールドを設定する場合でも、重要なときにスケーリングすることが真のニーズです。
次に、実装を簡素化するには、パーサーで値を検証できることが重要です。
第三に、解析と検証を 1 サイクルで完了することが重要です。これにより、Genericode ソリューションのような別のサイクルとパーサーで検証を行うことが回避されます。セットアップによっては、新しいテクノロジー要件を追加すると、コストや時間がかかりすぎる場合があります。
最後に、ソリューションは元のスキーマと下位互換性がある必要があります。互換性のないリストの変更を拡張機能と呼ぶことはできません。
列挙リストはまったく拡張すべきではないと考える人もいます。データ モデラーは、モデル にさらに多くのデータを含めてモデルを拡張したい場合、プロダクトに基づいてスキーマを作成できる、つまり、必要に応じて制約の少ないより大きなモデルを作成できると考えるかもしれません。元のスキーマとデータ モデルを制御できる場合は、これを行うことが可能であり、このアプローチが理想的である可能性があります。ただし、設計段階の後に実際に拡張する必要がある場合、そのようなアプローチは機能しません。
列挙リストを拡張する鍵は、XML スキーマ検証パーサーを使用しないことであると考える人もいます。 Genericode (「参考文献」を参照) では、最初の XML スキーマ・パーサー検証プロセスとは別に、第 2 レベルで列挙リストを検証することを推奨しています。この理論は正しく、この方法の応用はますます普及するでしょう。ただし、この解決策が 1 回の解析サイクル内で完了する必要がある場合は不可能です。場合によっては、2 回目の検証サイクルを実行できない場合があります。
もちろん、新しいリストに新しい要素を作成することもできます。ただし、raw モードとの下位互換性はありません。私たちの目標は、下位互換性を維持しながら拡張可能なリストを実現することです (「参考文献」を参照)。
この記事の目的上、ここでの仮定は、顧客と協力した私の経験、つまり、既存の列挙リストを付加価値で拡張する必要性に基づいています。また、XML スキーマの解析と検証は 1 つのステップで行われると想定しています。
列挙リストを拡張するための必要条件
この拡張例には 4 つの必要条件があります:
設計段階の後に列挙リストを拡張できるようにします。
パーサーを使用して列挙リストを検証します。
サイクル内で列挙リストを検証します。
オリジナルモードとの下位互換性を維持します。
たとえば、チームは地域の業界団体の列挙リスト (または既存のリスト) を処理し、用途に応じてスキーマ コンポーネントを変更する必要があります。リスト 1 に示すように、前のスキーマでは MaritalStatus コンポーネントと値の列挙リストが提供されていました。
リスト 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: 新しい列挙リストを作成し、元のリストに追加します。
2 番目のオプションは、新しい列挙リストを作成し、それを元の列挙リストに追加することです。リスト 1 は、元の婚姻状況リストを示しています。リスト 2 は、新しく作成された列挙リストを示しています。
リスト 2. 新しい婚姻状況列挙リスト
<xsd:simpleType name="MyExtMaritalStatusEnumType"> <xsd:restriction base="xsd:normalizedString"> <xsd:enumeration value="CivilUnion"/> </xsd:restriction> </xsd:simpleType>
リスト 3 に示すように、
リスト 3. 2 つの list グループを結合する
<xsd:simpleType name="MaritalStatusType_Union"> <xsd:union memberTypes="MyExtMaritalStatusEnumType MaritalStatusEnumType"/> </xsd:simpleType> <xsd:element name="MaritalStatus" type="MaritalStatusType_Union"/>
この解決策では、スキーマの編集がまだ必要です。つまり、MaritalStatus 要素を MaritalStatusType から MaritalStatusType_Union 型に変換する必要があります。大きな変更ではありませんが、手動での編集作業が必要です。 利点: 元の列挙リストは変更されません。
短所:
設計段階ですべての値を把握しておく必要があり、遅延バインディング ソリューションを防ぐことができます。
上に戻る
解決策 3: スキーマを作成し、プリミティブ列挙型と組み合わせる
次に、目の色に関する人口データの使用例を見てみましょう。リスト 4 にこのリストを示します。
リスト 4. 人の目の色の列挙リスト <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: という接頭辞が付いた任意の string です。 x: は、標準の列挙リストと拡張リストの間の区切り文字です。リスト 5 はこのパターンを示しています。 リスト 5. 展開用の正規表現
<xsd:simpleType name="StringPatternType"> <xsd:restriction base="xsd:string"> <xsd:pattern value="x:\S.*"/> </xsd:restriction> </xsd:simpleType>
リスト 6. 列挙リストと拡張モードの組み合わせ
<xsd:simpleType name="MyExtPersonEyeColorType"> <xsd:union memberTypes="PersonEyeColorType StringPatternType"/> </xsd:simpleType> <xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>
リスト 7. サンプル XML インスタンス
<PersonEyeColor>Black</PersonEyeColor> <PersonEyeColor>x:Teal</PersonEyeColor>
すべてのデータに同じ要素を使用できます。
パーサーを使用して基本的な列挙リストを検証します。
拡張値を明確に分離します。
このソリューションでは、後で新しい値をバインドすることができます。
欠点:
要素が展開されているかどうかを判断するには、要素の内容を解析する必要があります。
パターンパーサーは正規表現をサポートする必要があります。
トップに戻る
解決策 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>
プロパティ (拡張子) が必要です。リスト 9 にこのプロパティを示します。 リスト 9. 依存関係の拡張属性
<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. サンプル XML インスタンス
<DependentRelationship>Child</DependentRelationship> <DependentRelationship extension="MyNewRelationship">Extension</DependentRelationship>
优点:
不需要编辑原始模式。
该解决方案允许在以后绑定新值。
在原始模式中显式设计 extension 方法。
缺点:
在设计阶段,必须在每个枚举列表中设计 extension 方法。
必须在元素中而不是在属性中设置枚举值。
回页首
解决方案 5: 基于文档的方法 —— 与字符串结合
注意:解决方案 5 和解决方案 6 违反了在一个周期内进行验证 这一要求。但是,我之所以在这里介绍它们,是因为在很多实际环境中可以使用这些方法。
在第 5 个解决方案中,使用
清单 11 显示通过
清单 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"/>
优点:可以添加任意的扩展值,即使在后期绑定时也可以添加。
缺点:
解析器不验证枚举值,在第二个步骤中才进行验证。
需要
回页首
解决方案 6: 基于文档的方法 —— 使用
要使用该方法,将实际的枚举值放到
清单 12. 在
<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 模式特性。
缺点:解析器不验证枚举值。
回页首
未讨论的方法
我省略了其他几种扩展枚举列表的解决方案。下面简单介绍了两种没有使用的方法:
使用
使用 substitutionGroup 元素替换包含所有值的联合列表: 另外一种出色的解决方案,使用了替换组和联合。将原始列表与新列表联合以创建一个完整的枚举列表,然后使用 substitutionGroups 标记(或
回页首
结束语
XML 模式设计者和实现人员需要一种方法来扩展现有的枚举列表。因为一旦原始列表创建后,规范不允许进行扩展,因此需要找到一种方法实际实现扩展。实现人员可以使用本文的示例来设计和扩展枚举列表。每种方法都有优缺点,没有一种方法在所有用例中都是最佳方法。那么,应该使用哪种方法呢?
请考虑这些经验法则:
如果您习惯编辑原始枚举列表或模式,而且在设计阶段就知道所有要扩展的枚举值,最好使用 解决方案 1(手动编辑原始列表)或 解决方案 2(创建新列表并加入到原始列表中)。
如果想使用相同的语义元素来包含基本枚举列表和扩展枚举列表,可以考虑 解决方案 3(与模式联合)。
如果允许原始列表与扩展列表有不同的字段,可以使用 解决方案 4(独立的字段)。
如果不想在解析器中解析枚举值,可以考虑 Genericode 方法或使用 解决方案 5 或 解决方案 6。
这些指导原则可以使模式设计者找到实用的最佳实践,而且可以帮助他们创建易于实现、可扩展的枚举列表。
XML 模式和 XML 实例示例 ExtendEnumeratedListsCode.zip 2KB
以上がXMLスキーマの列挙型リストを拡張するサンプルコードの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。