【PHP8.x】schemaValidateメソッドの使い方

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

作成日: 更新日:

基本的な使い方

schemaValidateメソッドは、Dom\HTMLDocumentオブジェクトが表すHTMLドキュメントが、指定されたスキーマのルールに準拠しているかを検証するメソッドです。Dom\HTMLDocumentクラスは、HTMLドキュメントを解析し、操作するための機能を提供します。

このschemaValidateメソッドは、HTMLドキュメントの構造や内容が、あらかじめ定義されたDTD(Document Type Definition)やXML Schemaなどの形式で記述されたルールセットに厳密に適合しているかをチェックします。システムエンジニアを目指す初心者の方にとって、「スキーマバリデーション」とは、HTMLの記述が文法的に正しく、要素の配置や必須属性などが定められたルールに従っているかを確認する作業と理解していただければよいでしょう。

メソッドは通常、検証に使用するスキーマファイルのパスを引数として受け取ります。そして、検証プロセスを実行し、ドキュメントがスキーマに完全に準拠している場合はブール値のtrueを、何らかのルール違反が見つかった場合はfalseを返します。検証に失敗した場合、PHPは警告メッセージを生成することがあり、詳細なエラー情報は別途取得できる場合があります。

この機能は、外部から受け取ったユーザー入力のHTMLコンテンツが安全で適切な構造を持っているかを検証する際や、アプリケーションが動的に生成するHTMLが常に仕様に沿った正しい形式であることを保証する際に非常に役立ちます。これにより、予期しない表示崩れや処理エラーを防ぎ、より堅牢で信頼性の高いウェブアプリケーションの構築に貢献します。開発の初期段階で構造的な問題を特定し、デバッグ工数を削減するためにも重要なメソッドです。

構文(syntax)

1<?php
2
3$htmlDocument = new Dom\HTMLDocument();
4$htmlDocument->schemaValidate('path/to/your/schema.xsd');
5
6?>

引数(parameters)

string $filename, int $flags = 0

  • string $filename: 検証するHTMLファイルのパスを指定する文字列
  • int $flags = 0: 検証の挙動を制御するためのフラグを指定する整数。デフォルトは0(フラグなし)

戻り値(return)

bool

このメソッドは、HTMLドキュメントが指定されたXMLスキーマに準拠しているかどうかを検証し、その結果を真偽値(boolean)で返します。準拠している場合は true を、準拠していない場合は false を返します。

サンプルコード

PHP HTML スキーマ検証する

1<?php
2
3/**
4 * HTMLドキュメントをXSDスキーマに対して検証するサンプルコード。
5 *
6 * この関数は、指定されたHTML文字列を一時ファイルに保存し、
7 * 指定されたXSDスキーマ文字列も一時ファイルに保存した後、
8 * Dom\HTMLDocument::schemaValidate メソッドを使用して検証を行います。
9 * システムエンジニアを目指す初心者にも理解しやすいように、
10 * ドキュメントの準備から検証、結果表示までを簡潔に示します。
11 *
12 * @param string $htmlContent 検証するHTMLコンテンツ
13 * @param string $xsdSchemaContent 検証に使用するXSDスキーマコンテンツ
14 * @return void
15 */
16function validateHtmlWithSchema(string $htmlContent, string $xsdSchemaContent): void
17{
18    // 一時ファイル名の生成。システムの一時ディレクトリに作成されます。
19    $htmlFile = tempnam(sys_get_temp_dir(), 'html');
20    $xsdFile = tempnam(sys_get_temp_dir(), 'xsd');
21
22    if ($htmlFile === false || $xsdFile === false) {
23        echo "エラー: 一時ファイルの作成に失敗しました。\n";
24        return;
25    }
26
27    // HTMLコンテンツを一時ファイルに書き込みます。
28    if (file_put_contents($htmlFile, $htmlContent) === false) {
29        echo "エラー: HTMLコンテンツの一時ファイルへの書き込みに失敗しました。\n";
30        unlink($xsdFile); // 失敗時はもう一方のファイルもクリーンアップ
31        return;
32    }
33
34    // XSDスキーマコンテンツを一時ファイルに書き込みます。
35    if (file_put_contents($xsdFile, $xsdSchemaContent) === false) {
36        echo "エラー: XSDスキーマコンテンツの一時ファイルへの書き込みに失敗しました。\n";
37        unlink($htmlFile); // 失敗時はもう一方のファイルもクリーンアップ
38        return;
39    }
40
41    echo "--- 検証準備 ---\n";
42    echo "HTMLファイルパス: " . $htmlFile . "\n";
43    echo "XSDスキーマファイルパス: " . $xsdFile . "\n";
44    echo "--- 検証開始 ---\n";
45
46    try {
47        // Dom\HTMLDocument オブジェクトを作成します。
48        // このオブジェクトはHTMLドキュメントをDOMツリーとして扱います。
49        $doc = new Dom\HTMLDocument();
50
51        // libxml_use_internal_errors(true) を設定することで、
52        // DOMのパース中やスキーマ検証中に発生する警告やエラーを
53        // PHPの通常のエラー出力ではなく、libxml_get_errors() で取得できるようになります。
54        libxml_use_internal_errors(true);
55
56        // HTMLドキュメントを一時ファイルからロードします。
57        $doc->loadHTMLFile($htmlFile);
58        $loadErrors = libxml_get_errors(); // HTMLロード時のエラーや警告を取得
59        libxml_clear_errors(); // エラーバッファをクリア
60
61        if (!empty($loadErrors)) {
62            echo "警告: HTMLロード中に問題が検出されました。\n";
63            foreach ($loadErrors as $error) {
64                echo "  - " . trim($error->message) . " (Line: {$error->line})\n";
65            }
66        }
67
68        // ロードされたHTMLドキュメント(DOMツリー)をXSDスキーマに対して検証します。
69        // schemaValidateは成功した場合に true、失敗した場合に false を返します。
70        $isValid = $doc->schemaValidate($xsdFile);
71        $validationErrors = libxml_get_errors(); // スキーマ検証エラーを取得
72        libxml_clear_errors(); // エラーバッファをクリア
73
74        // エラーハンドリングを元の設定に戻します。
75        libxml_use_internal_errors(false);
76
77        if ($isValid) {
78            echo "結果: HTMLドキュメントはスキーマに適合しています。\n";
79        } else {
80            echo "結果: HTMLドキュメントはスキーマに適合していません。\n";
81            if (!empty($validationErrors)) {
82                echo "--- 検証エラー詳細 ---\n";
83                foreach ($validationErrors as $error) {
84                    echo "  - " . trim($error->message) . " (Line: {$error->line}, Column: {$error->column})\n";
85                }
86            } else {
87                echo "  (詳細なエラー情報は取得できませんでした。スキーマファイルのパスを確認してください。)\n";
88            }
89        }
90    } catch (Throwable $e) {
91        // 予期せぬ例外が発生した場合のハンドリング
92        echo "例外が発生しました: " . $e->getMessage() . "\n";
93    } finally {
94        // 作成した一時ファイルを削除し、クリーンアップします。
95        if (file_exists($htmlFile)) {
96            unlink($htmlFile);
97            echo "一時HTMLファイル ({$htmlFile}) を削除しました。\n";
98        }
99        if (file_exists($xsdFile)) {
100            unlink($xsdFile);
101            echo "一時XSDスキーマファイル ({$xsdFile}) を削除しました。\n";
102        }
103        echo "--- 検証終了 ---\n";
104    }
105}
106
107// 検証に使用するXSDスキーマの定義
108// このスキーマは、HTMLドキュメントが 'html' 要素を持ち、
109// その 'body' 要素内に 'main' 要素を必須とすることを定義しています。
110// 'main' 要素はオプションで 'h1' と 'p' を含めます。
111$simpleHtmlXsd = <<<'XSD'
112<?xml version="1.0" encoding="UTF-8"?>
113<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
114  <xs:element name="html">
115    <xs:complexType>
116      <xs:sequence>
117        <xs:element name="head" minOccurs="0"/>
118        <xs:element name="body">
119          <xs:complexType>
120            <xs:sequence>
121              <xs:element name="main"/> <!-- body内にmain要素を必須とする -->
122            </xs:sequence>
123          </xs:complexType>
124        </xs:element>
125      </xs:sequence>
126    </xs:complexType>
127  </xs:element>
128  
129  <xs:element name="main">
130    <xs:complexType>
131      <xs:sequence>
132        <xs:element name="h1" minOccurs="0"/>
133        <xs:element name="p" minOccurs="0"/>
134      </xs:sequence>
135    </xs:complexType>
136  </xs:element>
137</xs:schema>
138XSD;
139
140// --- サンプル1: スキーマに適合するHTMLでの検証 ---
141// このHTMLは、スキーマで定義された'body'内の'main'要素を含んでいます。
142$validHtml = <<<'HTML'
143<!DOCTYPE html>
144<html>
145<head>
146    <title>Valid HTML Document</title>
147</head>
148<body>
149    <main>
150        <h1>Welcome</h1>
151        <p>This is a valid HTML structure according to the schema.</p>
152    </main>
153</body>
154</html>
155HTML;
156
157echo "=== サンプル1: 適合するHTMLでの検証 ===\n";
158validateHtmlWithSchema($validHtml, $simpleHtmlXsd);
159echo "\n";
160
161// --- サンプル2: スキーマに適合しないHTMLでの検証 ---
162// このHTMLは、'body'要素内に必須である'main'要素がありません。
163$invalidHtml = <<<'HTML'
164<!DOCTYPE html>
165<html>
166<head>
167    <title>Invalid HTML Document</title>
168</head>
169<body>
170    <h1>Welcome</h1>
171    <p>This HTML is missing the required 'main' element inside 'body'.</p>
172</body>
173</html>
174HTML;
175
176echo "=== サンプル2: 適合しないHTMLでの検証 ===\n";
177validateHtmlWithSchema($invalidHtml, $simpleHtmlXsd);
178echo "\n";
179
180?>

PHP 8のDom\HTMLDocument::schemaValidateメソッドは、HTMLドキュメントが指定されたXSDスキーマのルールに適合しているかを検証するために利用されます。このメソッドは、HTMLドキュメントをDOM(Document Object Model)として扱うDom\HTMLDocumentクラスの機能の一部です。

引数としては、検証に使用するXSDスキーマのファイルパスを文字列(string $filename)で指定します。また、オプションで検証動作を制御するためのフラグを整数(int $flags = 0)で指定できますが、通常はデフォルト値の0で問題ありません。メソッドの戻り値はブール値(bool)で、HTMLドキュメントがスキーマに適合していればtrue、適合していなければfalseを返します。

サンプルコードでは、まず検証対象のHTMLコンテンツとXSDスキーマコンテンツをシステムの一時ファイルとして作成し、保存しています。その後、Dom\HTMLDocumentオブジェクトを生成し、loadHTMLFileメソッドで一時的なHTMLファイルを読み込み、DOMツリーとして準備します。この際、libxml_use_internal_errors(true)を設定することで、HTMLの読み込みやスキーマ検証中に発生する詳細なエラーメッセージを捕捉できるようにしています。

HTMLの準備が完了すると、$doc->schemaValidate($xsdFile)を呼び出し、読み込んだHTMLドキュメントとXSDスキーマファイルを照合して検証を実行します。この結果がtrueであればHTMLはスキーマに適合しており、falseであれば適合していません。適合しない場合は、捕捉したエラー情報を出力し、どの部分がスキーマに違反しているかを具体的に示します。最終的に、作成した一時ファイルはfinallyブロックで確実に削除され、システムをクリーンな状態に保ちます。これにより、HTMLの構造が意図通りに作られているかを自動で確認できます。

Dom\HTMLDocument::schemaValidateメソッドはXSDスキーマのファイルパスを引数として受け取ります。そのため、文字列形式のHTMLやXSDコンテンツを検証する際は、一時ファイルとして保存し、使用後は必ず削除するクリーンアップを徹底してください。一時ファイルの作成失敗時も適切にエラーハンドリングを行うことが重要です。

検証時にはlibxml_use_internal_errors(true)を設定して、DOMのパースやスキーマ検証で発生する詳細なエラー情報をlibxml_get_errors()で捕捉するようにしましょう。エラー情報を確認した後は、エラーバッファをクリアし、エラーハンドリング設定を元の状態に戻すことを忘れないでください。検証失敗はHTML構造の不適合だけでなく、XSDスキーマ自体の記述ミスが原因となる場合もありますので、スキーマの内容も正確に保つよう心がけてください。