web-dev-qa-db-ja.com

XMLスキーマを設計するためのベストプラクティスは何ですか?

アマチュアのソフトウェア開発者として(私はまだ学界にいます)、XML文書のスキーマをいくつか作成しました。私は、XMLのセマンティクスが正確に何であるかを完全に確信しているわけではないので、醜いXMLドキュメントを引き起こす設計フラブに日常的に出くわします。

私の仮定:

<property> value </property>

プロパティ=値

<property attribute="attval"> value </property>

特別な記述子を持つ属性、属性。

<parent>
  <child> value </child>
</parent>

親には、値「値」を持つ特性「子」があります。

<tag />

「タグ」はフラグであるか、直接テキストに変換されます。これについてはよくわかりません。

<parent>
  <child />
</parent>

「子供」は「親」を表します。 「子」はフラグまたはブール値です。これについてもわかりません。

デカルト座標を表すようなことをしたい場合、あいまいさが生じます。

<coordinate x="0" y="1 />

<coordinate> 0,1 </coordinate>

<coordinate> <x> 0 </x> <y> 1 </y> </coordinate>

どれが一番正しいですか? XMLスキーマ設計の現在の概念に基づいて、3番目に傾けようと思いますが、本当にわかりません。

XMLスキーマを効果的に設計する方法を簡潔に説明しているリソースは何ですか?

43
evizaer

チュートリアルを見る:

私もお勧めします:

17

一般的な(しかし重要です!)1つの推奨事項は、単一のノード(テキストノードであろうと属性ノードであろうと)に複数の論理的なデータを格納しないことです。そうしないと、独自の解析ロジックが必要になります上に通常フレームワークから無料で入手できるXML解析ロジック。

したがって、座標の例では、<coordinate x="0" y="1" />および<coordinate> <x>0</x> <y>1</y> </coordinate>はどちらも私には合理的です。

だが <coordinate> 0,1 </coordinate>は、1つのXMLノードに2つの論理的なデータ(X座標とY座標)を格納しているため、あまりよくありません。コンシューマにデータの解析を強いるoutside XMLパーサー。また、文字列をコンマで分割するのは非常に簡単ですが、最後に余分なコンマがあるとどうなるかなど、あいまいさがいくつかあります。

24
C. Dragon 76

オプション#2を回避するために、以下のcdragonのアドバイスに同意します。 #1と#3のどちらを選択するかは、主にスタイルの問題です。エンティティの属性と見なすものには属性を使用し、データと見なすものには要素を使用します。時々、分類するのは難しいです。それにもかかわらず、どちらも「間違った」ものではありません。

スキーマデザインのトピックについては、(要素と型の両方の)(最大)再利用の優先レベルに関する2セントを追加します。これにより、これらのエンティティの外部「論理」参照も容易になります。たとえば、データベースに格納されているデータ辞書。

「Garden of Eden」スキーマパターンは最大限の再利用を提供しますが、最も多くの作業を伴います。この投稿の最後に、ブログシリーズで取り上げた他のパターンへのリンクを示しました。

• エデンの園アプローチhttp://blogs.msdn.com/skaufman/archive/2005/05/10/416269.aspx

すべての要素をグローバルに定義することによりモジュール方式を使用し、ベネチアンブラインドアプローチと同様に、すべての型定義をグローバルに宣言します。各要素はノードの直接の子としてグローバルに定義され、そのtype属性は名前付きの複合型の1つに設定できます。
<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema targetNamespace="TargetNamespace" xmlns:TN="TargetNamespace" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  elementFormDefault="qualified" attributeFormDefault="unqualified"/> 
<xs:element name="BookInformation" type="BookInformationType"/> 
  <xs:complexType name="BookInformationType"/> 
    <xs:sequence> 
      <xs:element ref="Title"/> 
      <xs:element ref="ISBN"/> 
      <xs:element ref="Publisher"/> 
      <xs:element ref="PeopleInvolved" maxOccurs="unbounded"/> 
    </xs:sequence> 
  </xs:complexType> 
  <xs:complexType name="PeopleInvolvedType"> 
    <xs:sequence> 
      <xs:element name="Author"/> 
    </xs:sequence> 
  </xs:complexType> 
  <xs:element name="Title"/> 
  <xs:element name="ISBN"/> 
  <xs:element name="Publisher"/> 
  <xs:element name="PeopleInvolved" type="PeopleInvolvedType"/> 
</xs:schema>
このアプローチの利点は、スキーマを再利用できることです。要素とタイプの両方がグローバルに定義されているため、両方を再利用できます。このアプローチは、最大量の再利用可能なコンテンツを提供します。欠点は、スキーマが冗長であることです。これは、スキーマの要素と型のスコープ、および他のスキーマでのそれらの使用について、特に拡張性とモジュール性に関して想定する余裕がない一般的なライブラリを作成する場合に適切な設計です。


すべての異なるタイプと要素には単一のグローバル定義があるため、これらの標準的な粒子/コンポーネントは、データベース内の識別子と1対1で関連付けることができます。また、一見すると、テキストのXSDパーティクル/コンポーネントとデータベース間の関連付けを維持するのは面倒な手動タスクのように思えるかもしれませんが、SQL Server 2005は、実際には次のステートメントによって正規スキーマコンポーネント識別子を生成できます。

CREATE XML SCHEMA COLLECTION

http://technet.Microsoft.com/en-us/library/ms179457.aspx

逆に、SQL Server 2005では、標準的なパーティクルからスキーマを構築するために、

SELECT xml_schema_namespace function

http://technet.Microsoft.com/en-us/library/ms191170.aspx

ca・non・i・cal数学に関連しています。 (方程式、座標など)「最も単純または標準の形式」 http://dictionary.reference.com/browse/canonical

その他、構築は簡単ですが、再利用可能性が低い/「非正規化/冗長」なスキーマパターンは次のとおりです。

• ロシア人形のアプローチhttp://blogs.msdn.com/skaufman/archive/2005/04/21/410486.aspx

スキーマには、単一のグローバル要素(ルート要素)があります。他のすべての要素とタイプは徐々に深くネストされ、各タイプがその上のタイプに適合するため、名前が付けられます。このデザインの要素はローカルで宣言されているため、インポートまたはインクルードステートメントで再利用できません。

• サラミスライスアプローチhttp://blogs.msdn.com/skaufman/archive/2005/04/25/411809.aspx

すべての要素はグローバルに定義されますが、タイプ定義はローカルに定義されます。この方法で、他のスキーマが要素を再利用できます。このアプローチでは、ローカルに定義されたタイプを持つグローバル要素が要素のコンテンツの完全な説明を提供します。この情報「スライス」は個別に宣言されてから集約され、他のスキーマを構築するためにつなぎ合わせることもできます。

• ベネチアンブラインドアプローチhttp://blogs.msdn.com/skaufman/archive/2005/04/29/413491.aspx

どちらも単一のグローバル要素を使用するという点で、ロシアの人形のアプローチに似ています。ベネチアンブラインドアプローチでは、すべての型定義にグローバルに名前を付けて定義することにより、モジュール式のアプローチを説明します(要素をグローバルに宣言してローカルで型を宣言するサラミスライスアプローチとは対照的)。グローバルに定義された各タイプは個々の「スラット」を表し、他のコンポーネントで再利用できます。さらに、スキーマの上部にあるelementFormDefault属性の設定に応じて、ローカルで宣言されたすべての要素を名前空間修飾または名前空間非修飾(スラットを「開く」または「閉じる」)にすることができます。
11
6eorge Jetson

XMLはデザインの面でやや主観的です-要素と属性をどのようにレイアウトするかについては正確なガイドラインはないと思いますが、要素を使用して「もの」を表し、属性を使用して単一の属性/プロパティを表す傾向がありますそのうちの。

座標の例ではどちらも完全に許容できますが、私の傾向は<coordinate x="" y=""/>これは、いくぶん簡潔であり、ドキュメントの数が多いと、ドキュメントが少し読みやすくなります。

ただし、最も重要なことはスキーマの名前空間です。 (a)バージョンがあること、および(b)バージョンがそこにあることを確認してください。将来変更したり、新しいバージョンを発行したりできるようにするためです。バージョンは日付または数値のいずれかです。

http://company.com/2008/12/something/somethingelse/
urn:company-com:2008-12:something:somethingelse

http://company.com/v1/something/somethingelse/
urn:company-com:v1:something:somethingelse
3
Greg Beech

XMLドキュメントモデルを設計する方法についての良い学習リソースは知りません(スキーマはドキュメントモデルを指定する正式な方法にすぎません)。

私の意見では、XMLに対する重要な洞察の1つは、XMLは言語ではなく、構文です。また、各ドキュメントモデルは個別の言語です。

異なる文化はそれぞれ独自の特別な方法でXMLを使用します。 W3C仕様内でも、XSLTのダッシュで区切られた名前でLISPの匂いを嗅ぐことができ、XMLスキーマのcamelCaseNamesでJavaです。同様に、異なるアプリケーションドメインは異なるXMLイディオムを要求します。

[〜#〜] html [〜#〜] または DocBook などのナラティブドキュメントモデルでは、印刷可能なテキストをテキストノードに、メタデータを要素名と属性に配置する傾向があります。

[〜#〜] svg [〜#〜] などのよりオブジェクト指向のドキュメントモデルは、テキストノードをほとんどまたはまったく使用せず、代わりに要素と属性のみを使用します。

ドキュメントモデルの設計に関する私の個人的な経験則は次のようなものです。

  • それが mixed content を必要とするfree-fromタグスープのようなものである場合、インスピレーションのソースとしてHTMLとDocBookを使用してください。その他のルールは、それ以外の場合にのみ関連します。
  • 値が複合または階層になる場合は、要素を使用します。スペースで区切られた単純なシーケンスであるIDREFSなどの確立されたイディオムを除いて、XMLデータはこれ以上の解析を必要としません。
  • 値が複数回出現する必要がある場合は、要素を使用します。
  • 値をさらに調整する必要がある場合、または後で強化する必要がある場合は、要素を使用します。
  • 値が明らかにアトミック(ブール値、数値、日付、識別子、単純なラベル)であり、最大で1回発生する可能性がある場合は、属性を使用します。

別の言い方をすると、

  • それが物語であるならば、それはオブジェクト指向ではありません。
  • オブジェクト指向の場合は、オブジェクトを要素としてモデル化し、アトミック属性を属性としてモデル化します。

編集:一部の人は属性を完全に忘れたいようです。何も間違っていることはありませんが、ドキュメントを膨らませ、手作業で読み書きすることが不必要になるので、私はそれが嫌いです。

3
ddaa

私の会社のシステムをクライアントと統合するための一連のXMLスキーマを作成するように指定されました。 10年以上前にそのうちの数十を設計しましたが、仕様の拡張機能の多くが実際にはうまく機能しないことがわかりました。新しいものを設計する前に、現在のベストプラクティスを検索しました(そしてここに到着しました!)。

上記のヒントのいくつかは役に立ちますが、ほとんどすべてのリファレンスが好きではありませんでした。私が見つけたデザインの推奨事項が最も良い場所は、Microsoftからのものでした。

最良のリファレンスは XMLスキーマ設計パターン:複雑さの回避 です。ここにこの正気なアドバイスがあります:

多くのスキーマ作成者は、言語の難解な部分や特徴をすべて理解しようとするのではなく、W3C XMLスキーマによって提供される機能の効果的なサブセットを理解して利用することで最善を尽くすようです。

次のガイドラインの詳細な説明を与える:

  • グローバル要素宣言とローカル要素宣言を使用する理由
  • グローバルおよびローカルの属性宣言を使用する理由
  • XML名前空間がW3C XMLスキーマにどのように影響するかを理解する必要がある理由
  • ElementFormDefaultを常に「qualified」に設定する必要がある理由
  • 属性グループを使用する理由
  • モデルグループを使用する理由
  • 組み込みの単純型を使用する理由
  • 複合型を使用する理由
  • 表記法宣言を使用すべきでない理由
  • 置換グループを慎重に使用する必要がある理由
  • ID制約のためにID/IDREFよりもkey/keyref/uniqueを優先すべき理由
  • カメレオンスキーマを慎重に使用する理由
  • 特にxs:QNameのタイプに対して、デフォルト値または固定値を使用すべきでない理由
  • 単純型の制限と拡張を使用する理由
  • 複合型の拡張を使用する理由
  • 複合型の制限を慎重に使用する必要がある理由
  • 抽象型を慎重に使用する理由
  • ワイルドカードを使用して、明確に定義された拡張ポイントを提供する
  • グループまたはタイプの再定義を使用しないでください

彼らのアドバイスについての私のアドバイスは、彼らが「慎重に使用する」と言ったとき、あなたは単にそれを避けるべきだということです。スキーマの仕様はソフトウェア開発者によって作成されたのではないようです。彼らはいくつかのオブジェクト指向の概念を使用しようとしましたが、それを台無しにしました。拡張メカニズムの多くは役に立たないか、非常に冗長です。誰かがどのようにして複合型の制限を発明したのか、私にはよくわかりません。

このサイトには、さらに2つの素晴らしい記事があります。

そして、普及している1つのヒントは、公式仕様とは異なるものでスキーマを指定することです。 Relax NGは、最も好まれている仕様言語に見えます。残念ながら、標準化であるその最高の機能の1つを失うことになります。

1
neves

XMLベースのフォーマットを設計するとき、あなたが何を表しているのかを考えることはしばしば良いことです。意図した目的に合ったXMLデータをモックしてみてください。要件を満たし、要件を満たすものを手に入れたら、スキーマを開発して検証します。

フォーマットを設計するときは、データコンテンツを保持するための要素と、ID、名前、タイプ、または要素に含まれるデータに関するその他のメタデータなどのデータに特性を適用するための属性を使用する傾向があります。

その点で、座標のXML表現は次のようになります。

<coordinate type="cartesian">
  <ordinate name="x">0</ordinate>
  <ordinate name="y">1</ordinate>
</coordinate>

これは、さまざまな座標系に対応します。それらが常にデカルトであることを知っているなら、より良い実装は次のようになるでしょう:

<coordinate>
  <x>0</x>
  <y>1</y>
</coordinate>

もちろん、後者の場合、各要素の型を宣言する必要があるため、スキーマがより冗長になる可能性があります(ただし、これらの要素のハードワークを実際に実行するために複雑な型が定義されていると思います)。

プログラミングの場合と同じように、同じ目的を達成する方法は複数あることがよくありますが、多くの状況で善悪はありません。重要なことは、一貫性を保ち、直感的になるようにして、他の人があなたのスキーマを見て、あなたが達成しようとしていたことを理解できるようにすることです。

常にスキーマのバージョンを管理し、スキーマに対して作成されたXMLがそれを示していることを確認してください。 XMLを適切にバージョン管理しないと、古いスキーマに書き込まれたXMLをサポートしながらスキーマに補遺を作成することがはるかに難しくなります。

1
Jeff Yates

私たちのJavaプロジェクトでは、しばしば [〜#〜] jaxb [〜#〜] を使用して、XMLを自動的に解析し、それをオブジェクト構造に変換します。他の言語の人にも似たようなものがあると思います。適切なジェネレーターは、選択したプログラミング言語でオブジェクト構造を自動的に作成できます。これにより、多くの場合、システム間の通信用の移植可能なXML表現を維持しながら、XMLの処理がはるかに簡単になります。

このような自動マッピングを使用する場合、これによりスキーマが大幅に制約されることがわかります-<coordinate> <x> 0 </x> <y> 1 </y> </coordinate>は、翻訳で特別な魔法をかけたくない場合を除きます。スキーマで宣言された適切なタイプの2つの属性Coordinatexを持つクラスyになります。

1

あなたが表現しようとしているデータの関係を見てください私が見つけた最高のアプローチです。

0
Rob Wells

私はしばしば同じ問題に悩まされていますが、実際には問題ではなく、xmlは単なるデータです。

そうは言っても、私は通常、「ノードについて何かを言う場合は属性であり、そうでない場合は子ノードである」というアプローチを好みます。

あなたの例では私は行きます:

<coordinate>
    <x>0</x>
    <y>1</y>
</coordinate>

xとyは座標のプロパティであり、実際にはxmlについてではなく、それによって表されるオブジェクトについて何も言っていないからです。

0
Kris

デカルト座標を扱うときに、属性フォームがより扱いやすいことがわかりました。私のプロジェクトは複数の名前空間を必要とする傾向があり、名前空間間で座標タイプの定義を共有すると、サブ要素形式では醜くなります。サブ要素の形式では、サブ要素を修飾するか、ベース要素またはルート要素の名前空間を調整するか、デフォルトで非修飾要素名に設定する必要があります(例: namespace hiding

0
Caleb

おそらく、構造がどれほど複雑か単純かによって異なります。
xとyに独自の詳細がない限り、xとyを属性として作成します

何かを定義するために使用されるHTMLまたはその他の形式のマークアップ(WPFの場合はXAML、フラッシュの場合はMXML)を確認して、子ノードに対して何かが属性として選択されている理由を理解することができます。

xとyを繰り返さない場合は、属性にすることができます。

座標に複数のxとyがあるとしましょう。xmlでは、ノードに同じ名前の複数の属性を使用できないと思います。その場合、子ノードを使用する必要があります。

0
shahkalpesh

表現したいすべての値に対して要素またはサブ要素を使用することに本質的に問題はありません。

主な考慮事項は、属性を使用するほうがわかりやすい場合があることです。要素は特定の名前の属性を1つしか持つことができないため、1:1のカーディナリティで立ち往生しています。データを子要素として表す場合は、任意のカーディナリティを使用できます(または後で拡張することもできます)。

上記のRob Wellsの応答は正しいです。モデル化しようとしている関係に依存します。

1対1の関係以外には決してならないことが明らかにあるときはいつでも、属性はよりクリーンな場合があります。

0
BQ.

ここ は、XML文法を設計するための優れた方法のリストです。

上記のように、これは主観的な慣行ですが、このサイトは、「このパターンを使用して問題Xを解決する」…または「長所と短所は…」などの有用な指示を提供します。

0
Zearin