次の方法で共有


Schematron を使用して XML ドキュメント検証を向上する

Dare Obasanjo
Microsoft Corporation

September 2004

適用対象:
   XML
   Schematron

要約: Dare Obasanjo が、Schematron XML 検証言語を使用して W3C XML Schema の機能を超えた XML ドキュメントの制約を強制する方法について説明します。サンプル プログラム ファイル内では実際のコメント行は英語で書かれていますが、この記事内では説明目的で日本語で書かれています。この記事には英語のページへのリンクも含まれています。

この記事のコード サンプルをダウンロードするには、ここをクリックします。

目次

はじめに
Schematron の 6 つの基本要素
Schematron と W3C XML スキーマ検証を組み合わせる
.NET Framework で Schematron を使用する
まとめ

はじめに

XML スキーマは、ドキュメント内で使用可能な要素やそれらの要素を並べる順序を指定したり、要素の特定の状況に対する制約を記述したりして、XML ドキュメントの構造を記述するのに使用されます。XML および XML スキーマ言語の使用範囲が広がるにつれ、XML ドキュメント検証と XML スキーマに対して 2 つの主なシナリオが出来上がりました。

  1. XML ドキュメントのプロデューサとコンシューマ間の規約を記述および強制する: XML スキーマは、特定の XML ボキャブラリに基づいて有効な XML ドキュメントの構成要素を記述する、コンピュータで判読可能な極めて簡潔な方法です。そのため、スキーマは XML ドキュメントのプロデューサとコンシューマ間の "規約" と考えられます。通常、コンシューマは、プロデューサから受け取った XML ドキュメントをスキーマと照らし合わせて、ドキュメントが規約に従っていることを確認します。このような使用方法は、企業間での XML ドキュメントの交換から、XML 構成ファイルを使用するアプリケーションまで、さまざまな状況における広範囲な XML 使用シナリオに適用されます。
  2. XML ドキュメントとして表される型指定されたデータの処理および格納の基礎を作成する: リレーショナル データベースのコンテンツまたはプログラミング言語のオブジェクトなどの、構造や型指定の規定が厳しいデータを表す方法として XML が使用されるようになるにしたがって、XML ドキュメント内でデータ型を記述できるという必要性がより重要になってきました。そこで、入力 XML 情報セット (infoset) を、要素および属性の情報項目に型名で注釈が付けられる型注釈情報セット (TAI: Type Annotated Infoset) に変換する方法を提供する XML スキーマ言語が作成されました。「W3C XML Schema Recommendationleave-ms」では、ドキュメントをスキーマに照らし合わせて検証した結果として型注釈情報セットが作成されることについて説明しています。W3C XML Schema に対する検証の実行中に、入力 XML 情報セットは型注釈やその他の情報を含むスキーマ検証後の情報セット (PSVI: Post Schema Validation Infoset) に変換されます。ただし、実際には、型注釈情報セットを作成するのに完全なドキュメントの検証を行う必要はないことがわかっており、通常、XML とオブジェク間のマッピング技術など、XML スキーマを使用して型指定の厳しい XML を作成する多くのアプリケーションでは完全なドキュメントの検証は行われません。

現在、最も広く使用されている XML スキーマ言語は W3C XSD (XML Schema Definition) 言語です。XSD は型注釈情報セットにかかわるシナリオに対応することはできますが、XML ドキュメントの構造に対する制約の記述となると、かなり制限があります。W3C XML Schema で有効な制約を使用して XML ボキャブラリ設計の一般的なイディオムを表せないleave-ms 例はたくさんあります。W3C XML Schema で記述できない制約のうち、次の 3 つがよく要求されます。

  1. 属性の選択を指定すること: たとえば、server-status 要素は server-uptime 属性または server-downtime 属性のいずれかを持つ必要があります。
  2. 要素と属性をモデル グループにグループ化すること: xs:sequence、xs:choice、xs:all などのコンポジタを使用して要素をグループ化することはできますが、要素と属性の両方をグループ化することはできません。たとえば、要素と属性のセットの選択を作成することはできません。
  3. 要素または属性の値に基づいてコンテンツ モデルを変化させること: たとえば、status 属性の値が available の場合、要素は uptime 子要素を持つ必要があります。そうでない場合は、downtime 子要素を持つ必要があります。このような制約を技術用語では共起制約と呼びます。

これらのイディオムは XML ボキャブラリの中で広く使用されていますが、W3C XML Schema を使用して記述することも可能です。ただし、メッセージ規約を強制するスキーマ検証に依存するのが難しくなります。この記事では、Schematron を使用して W3C XML Schema 言語にそのような機能を追加する方法を説明します。

Schematron の 6 つの基本要素

Schematron アサーション言語leave-ms では、XPath 式を使用した XML ドキュメントの有効性についてのアサーションを作成するメカニズムが提供されます。Schematron のドキュメントでは、schema、ns、pattern、rule、assert、および report の 6 つの要素が一般的に使用されます。Schematron アサーション言語によって使用される要素の名前空間 URI は http://www.ascc.net/xml/schematron です。

  1. <schema> 要素leave-ms: スキーマのドキュメント要素です。その子要素は、人間が読み取れるスキーマ名を含む title 要素、スキーマ内の XPath 式で使用される名前空間とプレフィックスのバインドを指定するのに使用される ns 要素、同時に実行する必要があるパターンのグループを記述する phase 要素、ドキュメントを検証するためのルールのグループを含む pattern 要素、ドキュメントのアサーションに失敗したときに詳しいエラー メッセージを提供するのに使用される 1 つ以上の diagnostic 要素を含む diagnostics 要素です。また、schema 要素は、id、version、schemaVersion、fpi、defaultPhase、および icon の属性を持ちます。以下に schema 要素の例を示します。

    <schema xmlns="http://www.ascc.net/xml/schematron"
    schemaVersion="1.01" >
    <title>A Schema for Books</title>
    <ns prefix="bk" uri="http://www.example.com/books" />
    <pattern id="authorTests">
    <rule context="bk:book">
    <assert test="count(bk:author)!= 0">
    A book must have at least one author
    </assert>
    </rule>
    </pattern>
    <pattern id="onLoanTests">
    <rule context="bk:book">
    <report test="@on-loan and not(@return-date)">
    Every book that is on loan must have a return date
    </report>
    </rule>
    </pattern>
    </schema>
    

  2. <ns> 要素leave-ms: この要素は、pattern、rule、および assert 要素内の XPath 式で使用されるプレフィックスと名前空間のバインドを指定するのに使用されます。プレフィックスがバインドされる名前空間のプレフィックスと名前を定義する、prefix 属性および uri 属性が必要です。以下に ns 要素の例を示します。

    <ns prefix="bk" uri="http://www.example.com/books" />
    

  3. <pattern> 要素leave-ms: pattern 要素には rule 要素のリストが含まれます。また、pattern 要素は、id、name、see、および icon の属性を持ちます。pattern 要素の主な目的は、類似するアサーションをグループ化し、検証過程の異なる段階で異なるパターンの組み合わせが実行される場面でフェーズを作成できるようにすることです。以下に pattern 要素の例を示します。

    <pattern id="authorTests"
    see="http://www.example.com/books/guidelines.html"
    name="Test for non-zero number of authors">
    <rule context="bk:book">
    <assert test="count(bk:author)!= 0">
    A book must have at least one author
    </assert>
    </rule>
    </pattern>
    

  4. <rule> 要素leave-ms: rule 要素には assert 要素および report 要素が含まれます。rule 要素は XPath 式を含む context 属性を持ちます。context 属性で指定される XPath 式に一致する入力ドキュメントからのすべてのノードは、 rule 要素内の assert 要素および report 要素それぞれに対してアサーションを満たすかどうかが検証されます。また、rule 要素は、マクロの挿入メカニズムを提供するのに使用される abstract 属性も持ちます。属性値が true の場合、rule 要素のコンテンツは別の rule 要素内に含めることができます。rule 要素は、抽象 rule を参照する 1 つ以上の extends 要素を持つことができます。検証中に、rule 要素の extends 要素は対象の抽象 rule のコンテンツに置き換えられます。また、rule 要素は、ドキュメントの部分間の相互参照を定義するメカニズムを提供する key 要素を持つこともできます。これは XSLT 内の key 要素leave-ms に似ています。key 要素は、一致する XPath 式を含む key 属性および path 属性を識別する name 属性を持ちます。以下に rule 要素の例を示します。

        <rule context="bk:book" role="authorCountRule">
    <assert test="count(bk:author)!= 0">
    A book must have at least one author
    </assert>
    </rule>
    

  5. <assert> 要素leave-ms: assert 要素は、要素のコンテンツ モデルについてのステートメント (つまり、アサーション) が true であるかどうかを検証するためのメカニズムを提供します。この要素の test 属性には XPath 式が含まれます。XPath の boolean() 関数を使用して XPath クエリ結果を Boolean 値に変換したときに false が返された場合、検証エラーが発生したことを意味します。この場合、assert 要素のコンテンツはエラー メッセージとして出力されます。assert 要素は、エラー メッセージに混合コンテンツ (要素と共に組み入れられたテキスト) を許可します。子として許可される要素のほとんどは視覚的なレイアウトを目的としており、HTML の p、emph、および dir を使用します。最後に、name 要素も子要素として許可されます。エラー メッセージが出力された場合、name 要素は context 要素の名前で置き換えられます。スキーマの作成者がエラー メッセージを再利用できるようにするために、assert 要素は、スキーマの diagnostics 要素内の 1 つ以上の diagnostic 要素を参照する diagnostics を持つことができます。こうすれば、検証エラーが発生した場合に、assert 要素のコンテンツと参照された diagnostic 要素のコンテンツの両方が出力されます。また、assert 要素は、id、role、subject、および icon の属性を持ちます。以下に assert 要素の例を示します。

    <assert test="count(bk:author)!= 0">
    A book must have at least one author
    </assert>
    

  6. <report> 要素leave-ms: report 要素は、1 つの重要な相違点を除くと assert 要素とまったく同じです。XPath の boolean() 関数を使用してテスト属性内の XPath クエリの結果を Boolean 値に変換したときに true が返された場合、検証エラーが発生したことを意味します。以下に report 要素の例を示します。

     <report test="@on-loan and not(@return-date)">
    Every book that is on loan must have a return date
    </report>
    

Schematron の要素の詳細については、ZVON Schematron referenceleave-ms のページを参照してください。

Schematron と W3C XML Schema 検証を組み合わせる

検証に Schematron を使用した場合、XML ドキュメントの構造の指定が面倒になるという 1 つの問題があります。一方、このタスクは W3C XML Schema では非常に簡単です。そこで、両者の長所を活かして、W3C XML Schema に Schematron ルールを埋め込むleave-ms ことを考えてみましょう。

W3C XML Schema 勧告は、特定のスキーマ要素の xs:annotation 内の xs:appinfo 要素にアプリケーション固有のデータを追加することによって、アプリケーションにスキーマ検証の拡張を許可します。これらの拡張ブロック内に Schematron の pattern 要素を埋め込むことができます。これはスキーマ検証プロセスの一部として適用されます。patterns 要素によって使用される名前空間は、スキーマの最上位で ns 要素を使用して xs:annotation 内に宣言する必要があります。以下に、埋め込まれた Schematron ルールを使用して、W3C XML Schema の機能を超えた制約を定義する W3C XML Schema の例を示します。具体的には、オプションの on-loan 属性が book 要素に割り当てられた場合、return-date 属性も必要であることが pattern 要素によって強制されています。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  
    xmlns:sch="http://www.ascc.net/xml/schematron"
    targetNamespace="http://www.example.com/books"
    xmlns:bk="http://www.example.com/books"
    elementFormDefault="qualified" >

  <xs:annotation>
    <xs:appinfo>
     <sch:title>Schematron validation</sch:title>
     <sch:ns prefix="bk" uri="http://www.example.com/books"/>
    </xs:appinfo>
   </xs:annotation>

 <xs:element name="books"> 
  <xs:complexType>
   <xs:sequence>  
    <xs:element name="book" type="bk:bookType" maxOccurs="unbounded">
      <xs:annotation>
       <xs:appinfo>
        <sch:pattern id="onLoanTests">
          <sch:rule context="bk:book">
           <sch:report test="@on-loan and not(@return-date)">
           Every book that is on loan must have a return date
           </sch:report>
          </sch:rule>
        </sch:pattern>
       </xs:appinfo>
      </xs:annotation>
    </xs:element>
   </xs:sequence> 
  </xs:complexType>
 </xs:element>

 <xs:complexType name="bookType">
  <xs:sequence>
   <xs:element name="title" type="xs:string" />
   <xs:element name="author" type="xs:string" />
   <xs:element name="publication-date" type="xs:date" />
  </xs:sequence>
  <xs:attribute name="publisher" type="xs:string" use="required" />
  <xs:attribute name="on-loan" type="xs:string"  use="required" />
  <xs:attribute name="return-date" type="xs:date"  use="required" />
 </xs:complexType>

</xs:schema>

.NET Framework で Schematron を使用する

XML スキーマに埋め込まれた Schematron ルールを使用することで柔軟性を向上するといっても、実際に .NET Framework で実行する方法がないと意味がありません。Microsoft XML MVP として表彰された Daniel Cazzulinoleave-ms によって実装された .NET Framework に対する Schematron の実装があります。これは Schematron.NETleave-ms と呼ばれ、Schematron スキーマ、および Schematron ルールが埋め込まれた XML スキーマに対して XML ドキュメントを検証するクラスを提供します。ほとんどのユーザーが Schematron.NET で直接作業するクラスは、NMatrix.Schematron.Validator クラスです。以下は、このクラスの API の概要です。

コンストラクタ

  1. Validate() を呼び出した結果として返される IXPathNavigable インスタンスが XmlDocument または XpathDocument のいずれであるべきかを示すオーバーロード。

    public Validator(NavigableType type)
    

  2. 出力形式を示すオーバーロード。

    public Validator(OutputFormatting format)
    

  3. 出力形式、および Validate() を呼び出した結果として返される IXPathNavigable インスタンスが XmlDocument または XpathDocument のいずれであるべきかを示すオーバーロード。

    public Validator(OutputFormatting format, NavigableType type)
    

  4. XPathDocument を Validate() メソッドによって返された IXPathNavigable 型に設定し、OutputFormatting.Log をフォーマッタとして使用する既定のコンストラクタ。

    public Validator()
    

プロパティ

  1. 評価のコンテキスト。

    public EvaluationContextBase Context { get; set; }
    

  2. Validate() メソッドによって返される型 (XmlDocument または XpathDocument)。

    public NavigableType ReturnType { get; set; }
    

  3. 検証結果の出力の生成に使用されるフォーマッタ。

    public IFormatter Formatter {get; set;}
    

  4. 検証過程でパターンを評価する必要のある phase 要素の識別子。

    public string Phase {get; set;}
    

メソッド

  1. スキーマの Validator のセットに、XML スキーマまたは Schematron ルール ファイルを追加。

    public void AddSchema(XmlSchema schema)
    public void AddSchema(Schema schema)
    public void AddSchema(Stream input)
    public void AddSchema(TextReader reader)
    public void AddSchema(XmlReader reader)
    public void AddSchema(string uri schema)
    

  2. スキーマの Validator のセットに、XML スキーマのコレクションまたは Schematron ルール ファイルを追加。

    public void AddSchemas(XmlSchemaCollection schemas)
    public void AddSchemas(SchemaCollection schemas)
    

  3. 提供された Schematron ルールに対して入力ドキュメントを検証。Schematron ルールが XML スキーマに埋め込まれている場合、XSD 検証は行われません。

    public void ValidateSchematron(IXPathNavigable source)
    public void ValidateSchematron(XPathNavigator nav)
    

  4. 提供されたスキーマに対して入力ドキュメントを検証。提供されたスキーマが Schematron ルールの埋め込まれた XML スキーマである場合、Schematron および XSD の両方の検証が行われます。

    public IXPathNavigable Validate(string uri)
    public IXPathNavigable Validate(Stream input)
    public IXPathNavigable Validate(XmlReader reader)
    public IXPathNavigable Validate(TextReader reader)
    

サンプル

以下のコード サンプルでは、この記事の「Schematron と W3C XML Schema 検証を組み合わせる」の XML スキーマに対して books.xml ファイルが検証されます。

using System;
using System.Xml;
using NMatrix.Schematron;

class Program{

  public static void Main(string[] args){

    try{
     Validator validator = new Validator();
     validator.AddSchema("books.xsd"); 
     validator.Validate(new XmlTextReader("books.xml"));
 
    }catch(Exception e){
      Console.WriteLine(e);
    }
  }
}

まとめ

この記事では、Schematron と W3C XML Schema の両方の長所を活かすことが可能であることを説明しました。XSD を使用して型指定された XML ドキュメントを作成しながら、スキーマ言語の宣言方法でビジネス ルールの詳細な検証を行うこともできます。.NET Framework を使用する開発者は、SourceForgeleave-ms のサイトまたはこの記事からダウンロードできるアセンブリから Schematron.NET をダウンロードして、Schematron を今日からでもご利用できます。

みなさんも XML 検証に Schematron を使用して両方の長所を活用してください。