目次へ

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は明確にしておく方がよいでしょう。

↑このページの先頭へ

こちらもチェック!

PR
  • XMLDB.jp