Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】DOMDocument::relaxNGValidateSource()メソッドの使い方

relaxNGValidateSourceメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

relaxNGValidateSourceメソッドは、DOMDocumentオブジェクトに読み込まれたXMLドキュメントが、指定されたRELAX NGスキーマのルールに従っているかを検証するメソッドです。RELAX NGは、XMLドキュメントの構造や内容を定義するためのスキーマ言語の一つで、これを利用することでXMLデータの一貫性と正確性を保証できます。

このメソッドを使用すると、外部から受け取ったXMLデータや、アプリケーション内で生成したXMLデータが、あらかじめ定められた形式に沿っているかを簡単にチェックすることが可能です。例えば、ウェブサービスから受信したXMLレスポンスが期待通りの構造をしているか、あるいは設定ファイルとして利用するXMLが正しいフォーマットであるかなどを確認する際に非常に役立ちます。

検証は、DOMDocumentオブジェクトにXMLドキュメントをロードした後、このメソッドの引数としてRELAX NGスキーマの内容を文字列として渡すことで実行されます。メソッドは、検証が成功した場合はtrueを、失敗した場合はfalseを返します。この戻り値を確認することで、検証結果に基づいた適切なエラー処理やビジネスロジックを実装し、データ連携の信頼性を高め、予期せぬエラーを防ぐ上で重要な役割を果たします。

構文(syntax)

1DOMDocument::relaxNGValidateSource(string $source): bool

引数(parameters)

string $source

  • string $source: RELAX NG スキーマを定義する XML 文字列

戻り値(return)

bool

このメソッドは、Relax NGスキーマを使用してDOMDocumentオブジェクトを検証します。検証に成功した場合はTRUEを、失敗した場合はFALSEを返します。

サンプルコード

PHP: DOMDocument::relaxNGValidateSourceでXML検証する

1<?php
2
3/**
4 * XMLデータが指定されたRelax NGスキーマに準拠しているかを検証します。
5 *
6 * この関数はDOMDocumentクラスのrelaxNGValidateSourceメソッドを使用し、
7 * XMLの構造や内容がRelax NGスキーマのルールに従っているかを確認します。
8 *
9 * @param string $xmlData 検証対象となるXML形式の文字列。
10 * @param string $relaxNgSchemaSource Relax NGスキーマの定義を含む文字列。
11 * @return bool XMLデータがスキーマに準拠していれば true、そうでなければ false。
12 */
13function validateXmlWithRelaxNg(string $xmlData, string $relaxNgSchemaSource): bool
14{
15    // DOMDocument オブジェクトを初期化します。
16    // XMLドキュメントを扱うためのクラスです。
17    $dom = new DOMDocument();
18
19    // XMLデータを読み込みます。
20    // loadXMLは、XML形式が不正な場合(例:閉じタグがない)に false を返します。
21    // @演算子は、loadXMLが発行する可能性のある警告(例:XML構文エラー)を抑制します。
22    if (!@$dom->loadXML($xmlData)) {
23        echo "エラー: XMLデータの読み込みに失敗しました。XMLの形式を確認してください。\n";
24        return false;
25    }
26
27    // Relax NGスキーマを使用して、読み込んだXMLがスキーマに準拠しているかを検証します。
28    // 検証に成功すれば true、失敗すれば false を返します。
29    // このメソッドも内部で警告を発生させることがあるため、@演算子で抑制しています。
30    return @$dom->relaxNGValidateSource($relaxNgSchemaSource);
31}
32
33// --- 使用例 ---
34
35// 1. Relax NGスキーマに準拠する有効なXMLデータ
36$validXml = <<<XML
37<bookstore>
38  <book category="cooking">
39    <title lang="en">Everyday Italian</title>
40    <author>Giada De Laurentiis</author>
41    <year>2005</year>
42    <price>30.00</price>
43  </book>
44</bookstore>
45XML;
46
47// 2. Relax NGスキーマに準拠しない無効なXMLデータ (price要素が不足)
48$invalidXml = <<<XML
49<bookstore>
50  <book category="cooking">
51    <title lang="en">Everyday Italian</title>
52    <author>Giada De Laurentiis</author>
53    <year>2005</year>
54    <!-- price 要素が不足しているため、スキーマ違反となります -->
55  </book>
56</bookstore>
57XML;
58
59// 3. XMLとして形式が不正なデータ (閉じタグがない)
60$malformedXml = <<<XML
61<bookstore>
62  <book category="cooking">
63    <title>...</title>
64  </book
65XML;
66
67
68// 検証に使用するRelax NGスキーマの定義
69// このスキーマは、bookstore内に1つ以上のbookがあり、
70// 各bookはcategory属性と、title, author, year, price要素を持つことを定義しています。
71$relaxNgSchema = <<<RNG
72<element name="bookstore" xmlns="http://relaxng.org/ns/structure/1.0">
73  <oneOrMore>
74    <element name="book">
75      <attribute name="category"/>
76      <element name="title">
77        <attribute name="lang"/>
78        <text/>
79      </element>
80      <element name="author">
81        <text/>
82      </element>
83      <element name="year">
84        <text/>
85      </element>
86      <element name="price">
87        <text/>
88      </element>
89    </element>
90  </oneOrMore>
91</element>
92RNG;
93
94
95echo "--- 有効なXMLの検証 ---\n";
96if (validateXmlWithRelaxNg($validXml, $relaxNgSchema)) {
97    echo "検証結果: 成功。XMLはRelax NGスキーマに準拠しています。\n";
98} else {
99    echo "検証結果: 失敗。XMLはRelax NGスキーマに準拠していません。\n";
100}
101
102echo "\n--- 無効なXML (スキーマ不適合) の検証 ---\n";
103if (validateXmlWithRelaxNg($invalidXml, $relaxNgSchema)) {
104    echo "検証結果: 成功。XMLはRelax NGスキーマに準拠しています。\n";
105} else {
106    echo "検証結果: 失敗。XMLはRelax NGスキーマに準拠していません。\n";
107}
108
109echo "\n--- 形式が不正なXMLの検証 ---\n";
110if (validateXmlWithRelaxNg($malformedXml, $relaxNgSchema)) {
111    echo "検証結果: 成功。XMLはRelax NGスキーマに準拠しています。\n";
112} else {
113    echo "検証結果: 失敗。XMLはRelax NGスキーマに準拠していません。\n";
114}

このサンプルコードは、PHPでXMLデータがRelax NGスキーマに準拠しているかを検証する方法を説明しています。主要な機能は、XMLドキュメントを扱うためのDOMDocumentクラスと、そのrelaxNGValidateSourceメソッドによって提供されます。

まず、DOMDocumentオブジェクトを新しく作成し、検証したいXML形式の文字列をloadXMLメソッドを使ってこのオブジェクトに読み込みます。この段階でXMLの構文が正しいかどうかが確認され、もし不正な形式であれば読み込みは失敗し、その後の検証は行われません。

XMLデータの読み込みが成功した後、relaxNGValidateSourceメソッドにRelax NGスキーマの定義を記述した文字列を引数として渡します。このメソッドは、読み込んだXMLデータが渡されたスキーマの構造や内容のルールに適合しているかを検査します。検証が成功し、XMLデータがスキーマに準拠していればtrueが戻り値として返されます。一方、スキーマに適合しない場合や、検証中に問題が発生した場合はfalseが返されます。

サンプルコードでは、XMLの読み込みや検証時に発生する可能性のある警告を@演算子で抑制し、処理をスムーズに進める工夫も示されています。このように、PHPの標準機能を使ってXMLデータの品質や整合性を自動的に検証することが可能です。

このサンプルコードは、XMLデータの形式が正しいかを確認し、さらにRelax NGスキーマに準拠しているかを検証するものです。コード中に使われている@演算子は、PHPが発行する警告メッセージを表示させないようにする便利な機能ですが、デバッグ時には問題を見逃す原因となるため、開発中は使用を控え、エラーログへの記録など適切なエラーハンドリングを検討することが重要です。また、XMLがスキーマに準拠しない場合、戻り値からは具体的なエラー内容が分かりません。より詳細な検証エラー情報を得るには、libxml_get_errors()のような関数を合わせて利用すると良いでしょう。外部から受け取るXMLデータは常に信頼できるとは限らないため、このような検証処理は、データ整合性やセキュリティ確保のために非常に重要となります。

PHP DOMDocument::relaxNGValidateSourceでXML検証する

1<?php
2
3/**
4 * DOMDocument::relaxNGValidateSource() メソッドの利用例を示します。
5 *
6 * この関数は、XML ドキュメントを RelaxNG スキーマ(文字列形式)に対して検証する方法を
7 * 初心者のシステムエンジニアにも分かりやすく解説します。
8 * 以下の3つのシナリオをカバーします。
9 * 1. 有効なXMLと有効なRelaxNGスキーマ
10 * 2. 無効なXMLと有効なRelaxNGスキーマ(検証失敗の例)
11 * 3. 有効なXMLと不正な形式のRelaxNGスキーマ(DOMException発生の例)
12 */
13function demonstrateRelaxNGValidateSource(): void
14{
15    // 1. 有効なXMLドキュメントの定義
16    $validXml = <<<XML
17<?xml version="1.0" encoding="UTF-8"?>
18<bookstore>
19    <book id="bk101">
20        <title>Everyday Italian</title>
21        <author>Giada De Laurentiis</author>
22    </book>
23</bookstore>
24XML;
25
26    // 2. XMLに対応するRelaxNGスキーマ(RNC形式)の定義
27    // このスキーマは、<bookstore>要素内に<book>要素が必須で、
28    // <book>要素は'id'属性、<title><author>子要素を持つことを定義します。
29    $validRelaxNgSchema = <<<RNC
30element bookstore {
31    element book {
32        attribute id { text },
33        element title { text },
34        element author { text }
35    }
36}
37RNC;
38
39    echo "--- シナリオ1: 有効なXMLを有効なRelaxNGスキーマで検証 ---\n";
40    $dom1 = new DOMDocument();
41    // XMLを読み込む
42    if (!$dom1->loadXML($validXml)) {
43        echo "エラー: シナリオ1の有効なXMLのロードに失敗しました。\n";
44        return;
45    }
46
47    try {
48        // DOMDocument::relaxNGValidateSource() を使用して検証を実行します。
49        // 引数にはRelaxNGスキーマの文字列を渡します。
50        // 検証が成功した場合は true、失敗した場合は false を返します。
51        if ($dom1->relaxNGValidateSource($validRelaxNgSchema)) {
52            echo "結果: 検証成功。XMLドキュメントはスキーマに対して有効です。\n";
53        } else {
54            echo "結果: 検証失敗(予期しない)。XMLドキュメントはスキーマに対して有効ではありませんでした。\n";
55        }
56    } catch (DOMException $e) {
57        echo "エラー: 予期しないDOMExceptionが発生しました: " . $e->getMessage() . "\n";
58    }
59
60    echo "\n--- シナリオ2: 無効なXML(スキーマにない要素の欠落)を有効なRelaxNGスキーマで検証 ---\n";
61    // スキーマで必須とされている <author> 要素が欠落しているXML
62    $invalidXml = <<<XML
63<?xml version="1.0" encoding="UTF-8"?>
64<bookstore>
65    <book id="bk102">
66        <title>Learning PHP</title>
67        <!-- <author>要素が欠落しているため、スキーマ違反となります -->
68    </book>
69</bookstore>
70XML;
71
72    $dom2 = new DOMDocument();
73    if (!$dom2->loadXML($invalidXml)) {
74        echo "エラー: シナリオ2の無効なXMLのロードに失敗しました。\n";
75        return;
76    }
77
78    // 検証エラーの詳細を捕捉するために、libxmlの内部エラー処理を有効にします。
79    libxml_use_internal_errors(true);
80    try {
81        // 無効なXMLなので、検証は失敗し false が返されることを期待します。
82        if ($dom2->relaxNGValidateSource($validRelaxNgSchema)) {
83            echo "結果: 検証成功(予期しない)。XMLドキュメントはスキーマに対して有効です。\n";
84        } else {
85            echo "結果: 検証失敗(予期通り)。XMLドキュメントはスキーマに対して有効ではありません。\n";
86            // 検証失敗の理由をlibxmlエラーから取得して表示します。
87            $errors = libxml_get_errors();
88            foreach ($errors as $error) {
89                echo "  検証エラー: " . trim($error->message) . "\n";
90            }
91        }
92    } catch (DOMException $e) {
93        echo "エラー: 予期しないDOMExceptionが発生しました: " . $e->getMessage() . "\n";
94    } finally {
95        // libxmlのエラーをクリアし、エラー処理モードを元に戻します。
96        libxml_clear_errors();
97        libxml_use_internal_errors(false);
98    }
99
100    echo "\n--- シナリオ3: 有効なXMLを不正な形式のRelaxNGスキーマで検証 ---\n";
101    // 閉じ括弧が欠落している、不正な形式のRelaxNGスキーマ
102    $malformedRelaxNgSchema = <<<RNC
103element bookstore {
104    element book {
105        attribute id { text },
106        element title { text }
107        // <book>要素の閉じ括弧が欠落しており、スキーマが不正です
108RNC;
109
110    $dom3 = new DOMDocument();
111    // ここではシナリオ1で使用した有効なXMLを再利用します。
112    if (!$dom3->loadXML($validXml)) {
113        echo "エラー: シナリオ3の有効なXMLのロードに失敗しました。\n";
114        return;
115    }
116
117    echo "不正な形式のRelaxNGスキーマで検証を試みます...\n";
118    try {
119        // 不正な形式のスキーマが渡された場合、DOMExceptionがスローされることが期待されます。
120        if ($dom3->relaxNGValidateSource($malformedRelaxNgSchema)) {
121            echo "結果: 検証成功(予期しない)。\n";
122        } else {
123            echo "結果: 検証失敗(予期しない、例外がスローされるはずです)。\n";
124        }
125    } catch (DOMException $e) {
126        echo "結果: 予期されたDOMExceptionを捕捉しました。不正なスキーマが原因のエラーです: " . $e->getMessage() . "\n";
127    }
128}
129
130// 関数を実行してデモンストレーションを開始します。
131demonstrateRelaxNGValidateSource();
132

PHP 8のDOMDocument::relaxNGValidateSource()メソッドは、XMLドキュメントの内容が特定のルール(RelaxNGスキーマ)に沿っているかを検証する際に使用されます。このメソッドは、DOMDocumentオブジェクトにロードされたXMLデータに対し、引数 $source で渡されたRelaxNGスキーマの文字列を適用して検証を行います。RelaxNGスキーマは、XMLの構造、要素、属性などのルールを定義するための言語です。

検証が成功し、XMLドキュメントがスキーマの定義に完全に合致する場合は true を、合致しない場合は false を戻り値として返します。システムエンジニアとして、外部から受け取ったXMLデータの整合性を確認したり、アプリケーション内部で生成したXMLが規定のフォーマットに準拠しているかをチェックする際に非常に役立ちます。

もし引数として渡されるRelaxNGスキーマの文字列自体が文法的に不正である場合、検証が始まる前に DOMException がスローされることがありますので、例外処理を適切に行うことが重要です。サンプルコードでは、有効なXMLとスキーマによる正常な検証、スキーマに準拠しない無効なXMLでの検証失敗、そして不正な形式のスキーマが与えられた場合の例外発生という、三つの典型的なシナリオを通じて、本メソッドの挙動とエラーハンドリングのポイントを具体的に示しています。特に、検証失敗時にはlibxml_use_internal_errorsを使用することで詳細なエラーメッセージを取得できる点も確認できます。

DOMDocument::relaxNGValidateSourceメソッドは、RelaxNGスキーマの文字列を引数にXMLドキュメントの検証を行い、結果をboolで返します。スキーマの構文が不正な場合、DOMExceptionが発生するため、try-catchブロックでのエラーハンドリングが必須です。検証がfalseを返す場合、具体的な失敗原因はlibxml_use_internal_errors(true)を設定しlibxml_get_errors()で取得できますが、使用後は必ずlibxml_clear_errors()libxml_use_internal_errors(false)で元の状態に戻してください。このメソッドは、DOMDocument::loadXML()などでXMLドキュメントが事前にロードされている必要があります。

関連コンテンツ

関連IT用語

関連プログラミング言語