- PR -

子要素の宣言方法 ref属性とtype属性

1
投稿者投稿内容
豪雪地帯
常連さん
会議室デビュー日: 2004/06/08
投稿数: 34
投稿日時: 2004-11-29 11:52
XMLスキーマを勉強中です。
子要素の宣言方法ですが、
"ref属性"でするのか、"type属性"でするのか、迷っています。
基準、ないしは指針のようなものがありましたら、ご教授願います。

例えば、以下の2通りの宣言方法ができると思います。
(8行目の宣言とその関連の13行目以降が異なっています)

宣言方法1:"ref属性"での宣言
1:<?xml version="1.0"?>
2:<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3:
4:<xsd:element name="customer">
5:<xsd:complexType>
6: <xsd:sequence>
7: <xsd:element name="name" type="xsd:string"/>
8: <xsd:element ref="address"/>
9: </xsd:sequence>
10:</xsd:complexType>
11:</xsd:element>
12:
13:<xsd:element name="address">
14:<xsd:complexType>
15:<xsd:sequence>
16:<xsd:element name="prefecture" type="xsd:string"/>
17:<xsd:element name="city" type="xsd:string" />
18:<xsd:element name="street" type="xsd:string" />
19:</xsd:sequence>
20:</xsd:complexType>
21:</xsd:element>
22:
23: </xsd:schema>


宣言方法2:"type属性"での宣言
1: <?xml version="1.0"?>
2: <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3:
4: <xsd:element name="customer">
5: <xsd:complexType>
6: <xsd:sequence>
7: <xsd:element name="name" type="xsd:string"/>
8: <xsd:element name="address" type="address_type"/>
9: </xsd:sequence>
10:</xsd:complexType>
11:</xsd:element>
12:
13:<xsd:complexType name="address_type">
14:<xsd:sequence>
15:<xsd:element name="prefecture" type="xsd:string"/>
16:<xsd:element name="city" type="xsd:string" />
17:<xsd:element name="street" type="xsd:string" />
18:</xsd:sequence>
19:</xsd:complexType>
20:
21: </xsd:schema>

type属性での宣言では、当然ながら、型を新規に追加宣言しなくては
なりません。ref属性の場合はそういう必要がありません。
ただ、ref属性での宣言はあまり見かけませんが、何か理由があるので
しょうか。

上記は以下の内容を参考にしています。
http://www.atmarkit.co.jp/fxml/rensai2/schema02/schema02.html
http://www.atmarkit.co.jp/fxml/tecs/020xsd/20.html

よろしくお願いします。
TAKABE
常連さん
会議室デビュー日: 2003/05/14
投稿数: 43
投稿日時: 2004-11-29 14:35
 豪雪地帯さま、こんにちは。
「要素をグローバルに宣言すべきか、ローカルに宣言すべきか」
 という問題ですね。いろいろな考え方があると思いますが、ひとまず機能的に違いが出ることとして、

(1) この要素が本当に他の要素やデータ型から参照される可能性はないかどうか

(2) 他の要素の子要素としてこの要素が出現する場合、親要素に応じてこの要素のデータ型を変更する必要性があるかどうか

 といったことなどがあげられるかと思います。

 まず(1)ですが、ある要素がいろいろな要素(もしくはその宣言に使われるデータ型)の子要素として出現するような場合には((2)に示すような例外を省けば)、グローバルに要素を宣言しておいて、それを参照する方法が自然な書き方と言えるかもしれません(?)。それに対して、あるスキーマの中で、ある親要素の中だけにしか出現しない子要素は、グローバルに宣言してもローカルに宣言しても機能的な違いおきないはずです。(もちろん対象名前空間が設定されている場合でも、elementFormDefault="qualified"等を使って、同等になっているとしての話です) ただし、その場合でもちょっとした落とし穴に嵌る場合もあって、それは何かというと、後になってその要素を他のスキーマから参照したくなったような場合に違いが生じます。
 他のスキーマからこのスキーマがインポートされた場合でも、その別のスキーマから直接参照できる要素は、グローバルに宣言された要素だけです。上記2つの例どちらでもcustomer要素はグローバルに宣言されていますから、他のスキーマからこれを参照することができます。ところが、「address要素は参照したいが、customer要素は参照しない」としたいようなケースが生じた場合には、上記2つの例では違いが生じます。customer要素の宣言の中(もしくはcustomer要素の宣言に使われるデータ型定義の中)でaddress要素がローカルに宣言されている場合は、customer要素の参照なしに(もしくはcustomer要素の宣言に使われるデータ型定義の参照なしに)address要素を使うことができません。これに対して、address要素がグローバルに宣言されている場合には、customer要素の必要性云々に関係なく、直接address要素を参照できます。

 次に(2)ですが…
 例えば、foo要素という別の要素の子要素としてもaddress要素が出現すると仮定します。address要素がグローバルに宣言され、それをcustomer要素やfoo要素が参照する場合は、その子要素として出現するaddress要素はどちらの親要素の中で出現しようとも、同じデータ型(address_type)です。ところが、customer要素とfoo要素それぞれの宣言の中(もしくはcustomer要素やfoo要素の宣言に使われるデータ型定義の中)でaddress要素をローカルに宣言した場合、customer要素の子要素となるaddress要素と、foo要素の子要素となるaddress要素では、それぞれ異なるデータ型を割り当てることが可能になります。つまり、customer要素の子要素となるaddress要素にはaddress_typeデータ型を割り当てるが、foo要素の子要素となるaddress要素にはxsd:string型を割り当てたりとかhoge型を割り当てる…といったことが、ローカルに宣言する場合には可能となります。

 あくまで私個人の指針ですが、私の場合は、(2)のような親要素に応じてデータ型を変える同名の要素を宣言しないといけないようなケースを要求されない限りは、基本的に、要素はグローバルに宣言するようにしています。
 まあいろいろな考え方があると思うのですが…

[ メッセージ編集済み 編集者: TAKABE 編集日時 2004-11-29 17:25 ]
豪雪地帯
常連さん
会議室デビュー日: 2004/06/08
投稿数: 34
投稿日時: 2004-11-29 18:06
TAKABEさん、こんにちは。

グローバルな宣言と、ローカルな宣言というのを知らなかったので、TAKABEさんのコメントを読み返しながら、勉強しました。

そこで、まず確認ですが、
 element要素がschema要素の直子供として現れる場合はグローバルな要素宣言であり、
 complex要素の内容として現れる場合はローカルな要素宣言である。
と認識した(attribute要素もそう)のですが、合っていますか。

そうならば、それと質問の宣言を照らし合わせると、

 宣言方法1(ref属性宣言)のcustomerとaddress要素はグローバルな要素宣言で、
 宣言方法2(type属性宣言)ではcustomerのみがグローバルな要素宣言で、
  address_typeは単に複合型の定義である(element要素でないのでローカルな要素宣言
  とは違う)、

という事で合っているでしょうか。

で、それぞれのメリット・デメリットはTAKABEさんの(1)と(2)の通りですが、
TAKABEさんとしては、基本的には、宣言方法1(ref属性宣言)の方にするようにしている、
ということで間違いないでしょうか。

>あくまで私個人の指針ですが、私の場合は、(2)のような親要素に応じてデータ型を変える
>同名の要素を宣言しないといけないようなケースを要求されない限りは、
>基本的にグローバルに宣言するようにしています。
私もTAKABEさんに従おうと思います。


[ メッセージ編集済み 編集者: 豪雪地帯 編集日時 2004-11-29 18:08 ]
TAKABE
常連さん
会議室デビュー日: 2003/05/14
投稿数: 43
投稿日時: 2004-11-30 10:27
 豪雪地帯さん、こんにちは。

>そこで、まず確認ですが、
> element要素がschema要素の直子供として現れる場合はグローバルな要素宣言であり、
> complex要素の内容として現れる場合はローカルな要素宣言である。
>と認識した(attribute要素もそう)のですが、合っていますか。
   :
   :
>で、それぞれのメリット・デメリットはTAKABEさんの(1)と(2)の通りですが、
>TAKABEさんとしては、基本的には、宣言方法1(ref属性宣言)の方にするようにしている、
>ということで間違いないでしょうか。

 はい、そうです。

>>同名の要素を宣言しないといけないようなケースを要求されない限りは、
>>基本的にグローバルに宣言するようにしています。
>私もTAKABEさんに従おうと思います。

 まあ、これはあくまで色々な考え方がある中での「私流」の方法ですから、あくまで参考程度に考えてくださいませ(^^)
 一応、W3Cによる要素のグローバルな宣言とローカルな宣言の極めて簡単な比較の解説が

「XML Schema Part 0: Primer Second Edition」
3.3 Global vs. Local Declarations
http://www.w3.org/TR/xmlschema-0/#GlobalvsLocal

 にあります。

 ちなみに私の場合、データ型の定義についても、一応「データ型の再利用性」の可能性ということを考えて、「匿名の型定義」は使わずに、きちんと名前を付けてデータ型を定義した書き方を基本にしています。(これまた色々と異論が噴出しそうなところではあるのですが(^^;) )
めぐ
ベテラン
会議室デビュー日: 2004/11/09
投稿数: 86
お住まい・勤務地: 千葉県内
投稿日時: 2004-11-30 11:02
こんにちは。

私も最近XMLスキーマを勉強し始めたのですが、

引用:

TAKABEさんの書き込み (2004-11-29 14:35) より:
ただし、その場合でもちょっとした落とし穴に嵌る場合もあって、それは何かというと、後になってその要素を他のスキーマから参照したくなったような場合に違いが生じます。
 他のスキーマからこのスキーマがインポートされた場合でも、その別のスキーマから直接参照できる要素は、グローバルに宣言された要素だけです。



この落とし穴にはまった一人です。
他のあるXMLスキーマから一部の要素を利用しようと思っていたのですが、
グローバルに宣言されていない要素だったため、不可能であるということに
最近気づきました。^^;
TAKABE
常連さん
会議室デビュー日: 2003/05/14
投稿数: 43
投稿日時: 2004-11-30 11:25
 めぐさま、こんにちは。

>この落とし穴にはまった一人です。

 やはり、はまった方がおられたのですね
 再利用したい場合というのは、後になってから出てくることがやっぱりありますね

 どういうXML Schemaの書き方が理想的なのかというのは、いろいろと議論が分かれるところかと思うのですが、私が影響を受けたのは、W3Cの

Modularization of XHTML 1.0 - Second Edition
http://www.w3.org/TR/2004/WD-xhtml-modularization-20040218/

 によるところが大きいです。
 ここに出てくる書き方や考え方はとても勉強になりました。

[ メッセージ編集済み 編集者: TAKABE 編集日時 2004-11-30 12:34 ]
1

スキルアップ/キャリアアップ(JOB@IT)