- 8.1 Namespaceとは
- 8.2 Target Namespace
- 8.3 スキーマの指定
- 8.4 schemaLocation、noNamespaceSchemaLocation
- 8.5 まとめ
8.2 Target Namespace
XMLはメタ言語、つまり「言語を作るための言語」です。そして、作成した言語の構成を示すのがXML Schemaです。XML Schemaで、その言語に属する要素や属性、その構造などを定義していきます。では、そのXML Schemaで定義している言語は、どこのNamespaceに属しているのでしょうか。XML Schema文書中で宣言されたものは、XML SchemaのTarget Namespaceに属します。Target NamespaceはXML Schemaのルート要素、schema要素の属性、targetNamespaceの値で指定します。
<schema targetNamespace="本文書で定義している言語のNamespaceのURI"> ... </schema>
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/PO1" xmlns:po="http://www.example.com/PO1"> ... </xsd:schema>
以上の例では、targetNamespaceとして、"http://www.example.com/PO1"を指定しています。これより、この文書は"http://www.example.com/PO1"という名前の言語の構造を記述していることがわかります。
XML Schemaでは、ひとつのNamespaceのスキーマを、複数のファイルに分割して記述、保存することも出来ます。ファイルが分散している場合、include要素を使用して他のファイルの場所を指定します。
<include schemaLocation="スキーマのファイルのURI"/>
以下に例を示します。
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/PO1" xmlns:po="http://www.example.com/PO1"> ... </xsd:schema>
上のXML Schemaファイルをaddress.xsdとします。Target Namespaceは"http://www.example.com/PO1"です。
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/PO1" xmlns:po="http://www.example.com/PO1"> <include schemaLocation="http://www.example.com/schemas/address.xsd"/> ... </xsd:schema>
上のXML SchemaのTarget Namespaceも、address.xsdと等しく、 "http://www.example.com/PO1"です。上の文書には、include要素が指定されています。schemaLocation属性の値は"http://www.example.com/schamas/address.xsd" です。これより"http://www.example.com/PO1"Namespaceのスキーマはこのファイルと "http://www.example.com/schemas/address.xsd"、2つのファイルにわかれて規定されていることがわかります。
さて、XML SchemaではTarget Namespaceが指定されていないXML Schemaも許しています。このようなXML Schemaをカメレオンスキーマといいます。Target Namespaceを持たないXML Schemaのファイルは、includeされると、Target NamespaceがincludeしたXML Schemaの文書のTarget Namespaceに設定されます。例えば、以下のような、Target Namespaceを持たないXML Schemaがあったとします。ファイル名はchameleon.xsdです。
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:po="http://www.example.com/PO1"> ... </xsd:schema>
上のXML Schemaファイルを、下記の別のXML Schemaファイルより、includeします。
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/Parent" xmlns:p="http://www.example.com/Parent"> <include schemaLocation="http://www.example.com/schemas/chameleon.xsd"/> ... </xsd:schema>
上のXML SchemaのTargetNamespaceは "http://www.example.com/Parent"です。そして、chameleon.xsdをincludeしています。すると、chameleon.xsdのTarget Namespaceは、includeしたスキーマのTarget Namespace、 "http://www.example.com/Parent"に設定されます。chameleon.xsdに規定されている要素や属性は、 "http://www.example.com/Parent"という名前のNamespaceに属していると判断されます。このように、includeするXML Schemaが変わると、Target Namespaceも変化することから、カメレオンスキーマと呼ばれるのです。
このように、Target Namespaceは必ず設定しなければいけないものではありません。(実際、Namespaceが設定されていないXML SchemaをXML文書より参照する方法も後述します。)カメレオンスキーマは、任意のNamespaceに取り込むことが出来る「部品」という機能を持っているともいえます。けれども、わかりやすく、使用しやすいスキーマを作成したいのであれば、Namespaceを常に明確にしたほうがよいでしょう。カメレオンスキーマは、使用しないほうがよいと考えます。
カメレオンスキーマを使用する場合の問題点について、以下にもう少し詳しく説明します。例えば、以下のような、スキーマ文書があったとします。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- note that targetNamespace attribute is absent. --> <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element ref="familyName"/> <xs:element ref="firstName" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="familyName" type="xs:string"/> <xs:element name="firstName" type="xs:string"/> </xs:schema>
上のファイルを別のスキーマ文書よりincludeします。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://example.com"> <xs:include schemaLocation="above.xsd" /> <xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element ref="person" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
一見正しそうなこれらのスキーマも実は間違っています。above.xsdファイルの7行目をみてください。13行目のfamilynName要素を参照しようとしています。しかし、これでは参照できません。このカメレオンスキーマは、Target Namespaceが"http://example.com"であるスキーマよりincludeされています。これより、familyName要素は"http://example.com"という名前のNamespaceに属していることになります。よって、この要素宣言を参照するためには、以下のように書き換える必要があります。
<xs:element ref="bp:familyName" xmlns:bp="http://example.com"/>
それでは、別のTarget Namespace"http://www.foo.com"が設定されているXML Schemaファイルからincludeして、再利用出来るでしょうか。それは、不可能です。これにより、カメレオンスキーマの「任意のNamespaceより取り込める部品」という利点が奪われてしまうのです。さらに悪いことに、一部のバリデータはこのエラーを検出できません。あとで、適切な要素宣言が出現するだろうと判断するからです。
このように、カメレオンスキーマを作成すると、検出が困難なエラーの種を埋め込むことになりかねません。Namespaceは明確にしておく方がよいでしょう。