質問
職場では、別のオフライン アプリケーションにデータを渡すための XML ファイルを作成するよう求められています。このアプリケーションは、データの一部を更新するために 2 番目の XML ファイルを作成して返します。このプロセス中に、XML ファイルの構造について他のアプリケーションのチームと議論してきました。
私が思いついたサンプルは基本的に次のようなものです。
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something">
<TYPE modelNumber="something" vendor="something"/>
</ITEM>
</INVENTORY>
他のチームは、これは業界標準ではないため、属性はメタデータにのみ使用すべきであると述べました。彼らは次のように提案しました。
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
<TYPE>
<MODELNUMBER>something</MODELNUMBER>
<VENDOR>something</VENDOR>
</TYPE>
</ITEM>
</INVENTORY>
最初の方法を提案した理由は、作成されるファイルのサイズがはるかに小さいためです。転送中にファイルに含まれるアイテムは約 80,000 個になります。彼らの提案は実際には私が提案したものよりも 3 倍大きいことが判明しました。私は言及されていた謎の「業界標準」を検索しましたが、XML 属性はメタデータにのみ使用されるべきであるというものを見つけることができた最も近いものでしたが、議論は実際に何がメタデータであるかについてのものであると述べました。
長々と説明しましたが (申し訳ありません)、メタデータとは何なのかをどのように判断するのでしょうか。また、XML ドキュメントの構造を設計するときに、属性または要素をいつ使用するかをどのように決定すればよいでしょうか。
解決
私は次の経験則を使用します。
- 属性とは、色、ID、名前などの自己完結型のものです。
- 要素とは、独自の属性を持っているか、持つ可能性があるもの、または他の要素を含むものです。
つまり、あなたのものは近いのです。私なら次のようなことをしたでしょう:
編集:以下のフィードバックに基づいて元の例を更新しました。
<ITEM serialNumber="something">
<BARCODE encoding="Code39">something</BARCODE>
<LOCATION>XYX</LOCATION>
<TYPE modelNumber="something">
<VENDOR>YYZ</VENDOR>
</TYPE>
</ITEM>
他のヒント
属性に関する問題には次のようなものがあります。
- 属性には複数の値を含めることはできません(子要素は含めることができます)
- 属性は簡単に拡張できません(将来の変更に備えて)
- 属性で構造を記述することはできません (子要素は記述できます)
- 属性はプログラム コードで操作するのがより困難です
- 属性値を DTD に対してテストするのは簡単ではありません
属性をデータのコンテナとして使用すると、読み取りや保守が困難なドキュメントが作成されます。要素を使用してデータを記述するようにしてください。属性は、データに関連しない情報を提供する場合にのみ使用してください。
次のようにならないようにしてください (これは XML の使用方法ではありません)。
<note day="12" month="11" year="2002"
to="Tove" to2="John" from="Jani" heading="Reminder"
body="Don't forget me this weekend!">
</note>
「XML」は「eXtensible」の略です。 マークアップ 言語"。マークアップ言語はデータがテキストであることを意味します。 マークアップされた 構造または書式に関するメタデータを含む。
XHTML は、意図されたとおりに使用された XML の例です。
<p><span lang="es">El Jefe</span> insists that you
<em class="urgent">MUST</em> complete your project by Friday.</p>
ここでは、要素と属性の区別は明確です。テキスト要素はブラウザに表示され、属性は説明です。 どうやって それらを表示するには (ただし、そのように機能しないタグがいくつかあります)。
XML がマークアップ言語としてではなく、XML として使用されると混乱が生じます。 データのシリアル化 この言語では、「データ」と「メタデータ」の区別がより曖昧になります。したがって、要素と属性の選択は、次のようなものを除いて、多かれ少なかれ任意です。 できない 属性で表すことができます (feenster の回答を参照)。
XML 要素と XML 属性
XML は合意がすべてです。 まず、既存の XML スキーマや、コミュニティや業界内で確立された規則に従ってください。
本当にスキーマをゼロから定義する状況にある場合は、次の一般的な考慮事項を参考にしてください。 要素と属性の決定:
<versus>
<element attribute="Meta content">
Content
</element>
<element attribute="Flat">
<parent>
<child>Hierarchical</child>
</parent>
</element>
<element attribute="Unordered">
<ol>
<li>Has</li>
<li>order</li>
</ol>
</element>
<element attribute="Must copy to reuse">
Can reference to re-use
</element>
<element attribute="For software">
For humans
</element>
<element attribute="Extreme use leads to micro-parsing">
Extreme use leads to document bloat
</element>
<element attribute="Unique names">
Unique or non-unique names
</element>
<element attribute="SAX parse: read first">
SAX parse: read later
</element>
<element attribute="DTD: default value">
DTD: no default value
</element>
</versus>
使い方にもよるかもしれません。データベースから生成された構造化データを表すために使用される XML は、最終的にフィールド値が属性として配置される場合にうまく機能する場合があります。
ただし、メッセージ トランスポートとして使用される XML では、より多くの要素を使用した方が良い場合があります。
たとえば、回答で提案されているように、次の XML があるとします。
<INVENTORY>
<ITEM serialNumber="something" barcode="something">
<Location>XYX</LOCATION>
<TYPE modelNumber="something">
<VENDOR>YYZ</VENDOR>
</TYPE>
</ITEM>
</INVENTORY>
ここで、バーコードを印刷するために ITEM 要素をデバイスに送信したいと考えていますが、エンコード タイプは選択できます。必要なエンコードタイプをどのように表現すればよいでしょうか?遅ればせながら、突然、バーコードが単一の自動値ではなく、印刷時に必要なエンコーディングで修飾されている可能性があることに気づきました。
<ITEM serialNumber="something">
<barcode encoding="Code39">something</barcode>
<Location>XYX</LOCATION>
<TYPE modelNumber="something">
<VENDOR>YYZ</VENDOR>
</TYPE>
</ITEM>
重要なのは、構造を完全に修正するために名前空間とともに何らかの XSD または DTD を構築しない限り、オプションをオープンしたままにした方が最善の結果が得られる可能性があるということです。
IMO XML が最も役立つのは、それを使用して既存のコードを壊さずに変更できる場合です。
私はスキーマ設計で属性と属性に関して次のガイドラインを使用します。要素:
- 長期実行テキストに要素を使用します(通常、文字列または正規化されたストリングタイプのテキスト)
- 2 つの値がグループ化されている場合は、属性を使用しないでください (例:要素のeventStartDateおよびeventEndDate)。前の例では、StartDateおよびEndDateの属性を含む「イベント」の新しい要素があるはずです。
- 営業日、日付時刻、および数字 (例:カウント、量、レート)は要素でなければなりません。
- 最終更新などの非ビジネス時間要素は、有効期限が切れている必要があります。
- ハッシュ コードやインデックスなどのビジネス以外の数値は属性にする必要があります。* 型が複雑になる場合は要素を使用します。
- 値が単純なタイプで繰り返されない場合は、属性を使用します。
- xml:id および xml:lang は、XML スキーマを参照する属性である必要があります
- 技術的に可能な場合は属性を優先します。
属性の優先順位は、次のものを提供することです。
- 一意 (属性は複数回出現できません)
- 順序は関係ありません
- 上記のプロパティは継承可能です (これは、現在のスキーマ言語では「すべての」コンテンツ モデルがサポートしていないものです)
- 利点は、冗長性が低く、使用する帯域幅が少ないことですが、それが要素よりも属性を好む本当の理由ではありません。
追加した 技術的に可能な場合 属性を使用できない場合があるためです。たとえば、属性セットの選択などです。たとえば、(startDate と endDate) xor (startTS と endTS) を使用することは、現在のスキーマ言語では不可能です
XML スキーマが「すべての」コンテンツ モデルの制限または拡張を許可し始めたら、私はおそらくそれを削除するでしょう。
この質問に対する普遍的な答えはありません (私は W3C 仕様の作成に深く関与しました)。XML はさまざまな目的に使用できます。最も一般的なのは、テキストのようなドキュメント、データ、宣言型コードの 3 つです。データモデルとしてもよく使用します。これらのアプリケーションには、属性がより一般的な側面もあれば、子要素がより自然な側面もあります。さまざまなツールには、使いやすくしたり使いにくくしたりする機能もあります。
XHTML は、属性が自然に使用される領域の 1 つです (例:クラス='foo')。属性には順序がないため、一部の人にとってはツールの開発が容易になる場合があります。OTOH 属性は、スキーマがないと入力が難しくなります。また、名前空間属性 (foo:bar="zork") は、さまざまなツールセットで管理するのが難しいことがよくあります。ただし、いくつかの W3C 言語を調べて、一般的な混合言語を確認してください。SVG、XSLT、XSD、MathML はよく知られた言語の例であり、いずれも豊富な属性と要素を備えています。一部の言語では、複数の方法でそれを行うことができます。
<foo title="bar"/>;
または
<foo>
<title>bar</title>;
</foo>;
これらは構文的に同等ではないため、処理ツールでの明示的なサポートが必要であることに注意してください)
私のアドバイスは、アプリケーションに最も近い領域での一般的な慣行を確認し、どのツールセットを適用するかを検討することです。
最後に、名前空間と属性を区別してください。一部の XML システム (例:Linq) は、API の属性として名前空間を表します。私の意見では、これは醜く、混乱を招く可能性があります。
迷ったときは、 キス -- 属性を使用する明確な理由がないのに、なぜ属性と要素を混在させる必要があるのでしょうか。後で XSD を定義することにした場合も、最終的にはよりクリーンになります。その後、後で XSD からクラス構造を生成することにした場合も、それがより簡単になります。
100万ドルの質問!
まず第一に、今はパフォーマンスについてあまり心配しないでください。最適化された XML パーサーが XML をいかに速くリッピングするかに驚かれるでしょう。さらに重要なのは、将来に向けてどのようなデザインをしているかということです。XML が進化するにつれて、疎結合と相互運用性をどのように維持するのでしょうか?
より具体的に言うと、要素のコンテンツ モデルをより複雑にすることはできますが、属性を拡張するのは難しくなります。
データには要素を使用し、メタデータ (要素のデータに関するデータ) には属性を使用します。
要素が選択文字列の述語として表示されている場合、それは属性であるべきであるという兆候があります。同様に、属性が述語として使用されない場合、それは有用なメタデータではない可能性があります。
XML は人間が判読できるものではなく、機械が判読できるものであること、および大きなドキュメントの場合、XML は非常によく圧縮されることに注意してください。
他の人は要素と属性を区別する方法を説明していますが、より一般的な観点から、結果として得られる XML が小さくなるという理由ですべてを属性に入れるのは間違っています。
XML はコンパクトになるように設計されているのではなく、移植可能で人間が読めるように設計されています。転送中のデータのサイズを削減したい場合は、他のもの (たとえば、 Googleのプロトコルバッファ).
どちらにしても議論の余地はありますが、XML は実際のデータの「マークアップ」またはメタデータに使用されるべきであるという意味では、同僚の意見は正しいです。XML でドメインをモデル化する場合、メタデータとデータの間の境界線がどこにあるのかを判断するのが難しい場合があるという点では、あなたの意見は正しいです。実際には、マークアップ内のすべてが非表示になっているように見せかけ、マークアップの外側のデータのみが読み取れるようにします。この文書はそういう意味では意味があるのでしょうか?
XML は容量が大きいことで知られています。輸送や保管の場合、処理能力に余裕がある場合は、圧縮することを強くお勧めします。XML は反復性があるため、圧縮率が高く、場合によっては驚異的に圧縮されます。大きなファイルを元のサイズの 5% 未満に圧縮したことがあります。
あなたの立場を強化するもう 1 つのポイントは、他のチームがスタイルについて議論している一方で (ほとんどの XML ツールは、全属性のドキュメントを全 #PCDATA ドキュメントと同じくらい簡単に処理できるという点で)、あなたは実用性について議論しているということです。スタイルを完全に無視することはできませんが、技術的なメリットの方が重視されるべきです。
オブジェクトのプロパティを保存するためのどちらの方法も完全に有効です。現実的な考慮から離れるべきです。次の質問に答えてみてください。
- どの表現がデータの解析と生成の高速化につながりますか?
- どの表現がデータ転送の高速化につながりますか?
可読性は重要ですか?
...
それは主に好みの問題です。これが代替手段よりもコンパクトであると考えているため、可能であればグループ化には要素を使用し、データには属性を使用します。
たとえば、私が好むのは....
<?xml version="1.0" encoding="utf-8"?>
<data>
<people>
<person name="Rory" surname="Becker" age="30" />
<person name="Travis" surname="Illig" age="32" />
<person name="Scott" surname="Hanselman" age="34" />
</people>
</data>
...の代わりに....
<?xml version="1.0" encoding="utf-8"?>
<data>
<people>
<person>
<name>Rory</name>
<surname>Becker</surname>
<age>30</age>
</person>
<person>
<name>Travis</name>
<surname>Illig</surname>
<age>32</age>
</person>
<person>
<name>Scott</name>
<surname>Hanselman</surname>
<age>34</age>
</person>
</people>
</data>
ただし、たとえば 20 ~ 30 文字以内で表現しにくいデータがある場合、またはエスケープが必要な引用符やその他の文字が多数含まれている場合は、要素を分割する時期が来たと思います...おそらく CData ブロックを使用します。
<?xml version="1.0" encoding="utf-8"?>
<data>
<people>
<person name="Rory" surname="Becker" age="30" >
<comment>A programmer whose interested in all sorts of misc stuff. His Blog can be found at http://rorybecker.blogspot.com and he's on twitter as @RoryBecker</comment>
</person>
<person name="Travis" surname="Illig" age="32" >
<comment>A cool guy for who has helped me out with all sorts of SVn information</comment>
</person>
<person name="Scott" surname="Hanselman" age="34" >
<comment>Scott works for MS and has a great podcast available at http://www.hanselminutes.com </comment>
</person>
</people>
</data>
私たちが苦労して獲得したオブジェクト指向の直感を活用してみてはいかがでしょうか?通常、どれがオブジェクトでどれがそのオブジェクトの属性であるか、またはそれがどのオブジェクトを参照しているかを考えるのは簡単だと思います。
オブジェクトとして直観的に意味のあるものは、要素として適合します。その属性 (またはプロパティ) は、xml 内のこれらの要素の属性、または属性を持つ子要素になります。
例のような単純なケースでは、オブジェクト指向の類似は、どれが要素でどれが要素の属性であるかを理解するのに問題ないと思います。
いくつかの悪い情報をいくつか修正します。
@ジョン・バリンジャー:属性には任意の文字データを含めることができます。< > & " ' は < にエスケープする必要があります>&」そして '、 それぞれ。XML ライブラリを使用する場合は、XML ライブラリが自動的に処理します。
属性には、本当に必要であれば、base64 エンコードしてデータにするだけで、画像などのバイナリ データを含めることができます。URL。
@フィーンスター:IDS または NAMES の場合、属性にはスペースで区切られた複数の項目を含めることができます。これには数字が含まれます。細かい点には注意しますが、これによりスペースを節約できる可能性があります。
属性を使用すると、XML と JSON の競争力を維持できます。見る ファットマークアップ:脂肪マークアップの神話を一度に 1 カロリーずつ減らす.
この種の議論の結果にはいつも驚かされます。私にとって、データが属性に属するかコンテンツとして属するかを決定するための非常に単純なルールがあります。それは、データがナビゲート可能な部分構造を持っているかどうかです。
したがって、たとえば、非マークアップ テキストは常に属性に属します。いつも。
リストはサブ構造またはコンテンツに属します。時間の経過とともに埋め込まれた構造化サブコンテンツを含む可能性のあるテキストは、コンテンツに属します。(私の経験では、データの保存や交換に XML を使用する場合、マークアップ付きのテキストという現象は比較的少ないです。)
この方法で記述された XML スキーマは簡潔です。
みたいな事例を見るたびに、 <car><make>Ford</make><color>Red</color></car>
, 「作者は、make 要素内にサブ要素が存在すると思っていたのだろうか?」と思います。 <car make="Ford" color="Red" />
大幅に読みやすくなり、空白がどのように処理されるかなどについては疑問の余地がありません。
空白の処理ルールだけを考えれば、これは XML 設計者の明確な意図だったと思います。
これは、属性とマークアップの違いが明確に見られる HTML では非常に明確です。
- すべてのデータはマークアップの間にあります
- 属性は、このデータを特徴付けるために使用されます (例:フォーマット)
純粋なデータを XML として持っているだけの場合、違いはそれほど明確ではありません。データはマークアップの間に存在することも、属性として存在することもできます。
=> ほとんどのデータはマークアップの間にある必要があります。
ここで属性を使用したい場合:データは次の 2 つのカテゴリに分類できます。データと「メタデータ」(メタデータはレコードの一部ではありませんが、「形式のバージョン」、「作成日」など)を提示する必要があります。
<customer format="">
<name></name>
...
</customer>
次のように言うこともできます。「属性を使用してタグを特徴付け、タグを使用してデータ自体を提供します。」
私もフィーンスターさんの意見に同意します。可能であれば、属性から離れてください。要素は進化に適しており、Web サービス ツールキット間の相互運用性が向上しています。これらのツールキットでは、属性を使用してリクエスト/レスポンス メッセージをシリアル化することはできません。私たちのメッセージは Web サービス ツールキットのデータ (メタデータではない) であるため、これも理にかなっています。
属性は時間の経過とともに管理が難しくなりがちです。私は個人的に彼らとはいつも距離を置いています。要素ははるかに明示的で、パーサーとユーザーの両方が読み取り/使用できるようになります。
私がこれらを使用したのは、アセット URL のファイル拡張子を定義するときだけです。
<image type="gif">wank.jpg</image> ...etc etc
属性を拡張する必要がないことが 100% わかっている場合は、それらを使用できると思いますが、それを何回知っているでしょうか。
<image>
<url>wank.jpg</url>
<fileType>gif</fileType>
</image>