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

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

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

作成日: 更新日:

基本的な使い方

readOuterXmlメソッドは、XMLReaderオブジェクトが現在位置しているノードとその子孫ノードを含むXML全体を文字列として取得するメソッドです。このメソッドは、現在のノードの開始タグから終了タグまでのすべての内容を、XML形式の文字列として返します。

具体的には、<item><title>サンプル</title><price>1000</price></item>のようなXMLデータにおいて、もしXMLReaderが<item>ノードに位置している場合、readOuterXmlメソッドは<item><title>サンプル</title><price>1000</price></item>という文字列全体を返します。この機能は、特定のXML要素とその内部構造すべてを一度に処理したい場合や、取得したXMLフラグメントを別のXML処理系に渡したい場合などに非常に役立ちます。

このメソッドを実行しても、XMLReaderの内部ポインタは次のノードには移動しません。引き続き次のノードを読み進めるためには、別途read()メソッドを呼び出す必要があります。現在のノードが有効でない場合や、外部XMLが存在しない場合は空の文字列が返されることがあります。返される文字列は通常、UTF-8でエンコードされます。

構文(syntax)

1<?php
2
3$reader = new XMLReader();
4$reader->XML('<root><item id="1">Data</item></root>');
5
6// XMLドキュメントの次のノードを読み進める
7$reader->read(); // <root>
8$reader->read(); // <item id="1">
9
10// 現在のノード (<item id="1">Data</item>) とその子孫を含むXMLを文字列として取得
11$outerXmlString = $reader->readOuterXml();
12echo $outerXmlString; // 出力: <item id="1">Data</item>
13
14$reader->close();
15
16?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

string|false

現在のノードのXMLコンテンツを文字列として返します。ノードの終了に達した場合はfalseを返します。

サンプルコード

PHP XMLReader readOuterXmlで要素全体を取得する

1<?php
2
3/**
4 * XMLReader::readOuterXml() メソッドの使用例。
5 * この関数は、XMLファイルから指定されたタグの外部XML(タグ自身とその全ての子要素)を読み取り、表示します。
6 *
7 * @param string $xmlFilePath 読み込むXMLファイルのパス。
8 * @param string $targetTagName 外部XMLを取得したい要素のタグ名。
9 * @return void
10 */
11function displayOuterXmlOfSpecificTag(string $xmlFilePath, string $targetTagName): void
12{
13    // XMLReader オブジェクトを新しく作成します。
14    $reader = new XMLReader();
15
16    // 指定されたXMLファイルを開きます。
17    // ファイルが存在しない、または読み込みに失敗した場合はエラーを出力し終了します。
18    if (!$reader->open($xmlFilePath)) {
19        echo "エラー: XMLファイル '{$xmlFilePath}' を開けませんでした。\n";
20        return;
21    }
22
23    echo "--- XMLReader::readOuterXml() の使用開始 ---\n\n";
24
25    // XMLドキュメントをノード(要素、テキスト、コメントなど)ごとに読み進めます。
26    while ($reader->read()) {
27        // 現在のノードが要素(開始タグ)であり、かつターゲットのタグ名と一致する場合
28        if ($reader->nodeType === XMLReader::ELEMENT && $reader->name === $targetTagName) {
29            // readOuterXml() を呼び出すと、現在のノード(開始タグ)から
30            // それに対応する終了タグまでのXML全体(子孫ノードを含む)を文字列として取得します。
31            // 読み取りが成功するとXML文字列を、失敗すると false を返します。
32            $outerXml = $reader->readOuterXml();
33
34            if ($outerXml !== false) {
35                echo "タグ '<{$targetTagName}>' の外部XML:\n";
36                echo $outerXml . "\n\n";
37            } else {
38                echo "エラー: タグ '<{$targetTagName}>' の外部XMLを読み取れませんでした。\n";
39            }
40        }
41    }
42
43    // XMLReader オブジェクトによって使用されたリソースを解放します。
44    $reader->close();
45    echo "--- 処理終了 ---\n";
46}
47
48// 実行のために、一時的なXMLファイルを生成します。
49// 実際のアプリケーションでは、既存のXMLファイルへのパスを指定します。
50$xmlContent = <<<XML
51<?xml version="1.0" encoding="UTF-8"?>
52<catalog>
53    <book id="bk101">
54        <author>Gambardella, Matthew</author>
55        <title>XML Developer's Guide</title>
56        <genre>Computer</genre>
57        <price>44.95</price>
58        <publish_date>2000-10-01</publish_date>
59        <description>An in-depth look at creating applications with XML.</description>
60    </book>
61    <book id="bk102">
62        <author>Ralls, Kim</author>
63        <title>Midnight Rain</title>
64        <genre>Fantasy</genre>
65        <price>5.95</price>
66        <publish_date>2000-12-16</publish_date>
67        <description>A young man discovers his supernatural fate.</description>
68    </book>
69</catalog>
70XML;
71
72$tempXmlFile = 'books.xml';
73file_put_contents($tempXmlFile, $xmlContent);
74
75// 関数を呼び出し、'book' タグの外部XMLを読み取って表示します。
76displayOuterXmlOfSpecificTag($tempXmlFile, 'book');
77
78// 実行後に一時ファイルを削除します(任意)。
79unlink($tempXmlFile);
80

PHP 8のXMLReader::readOuterXml()メソッドは、XMLドキュメント内の現在の要素ノードを、その開始タグから終了タグまですべて含む文字列として取得します。この「外部XML」には、要素自身だけでなく、その内部にある全ての子要素やテキストなども含まれます。引数はなく、成功時にはXML文字列を、失敗時にはfalseを戻り値として返します。

サンプルコードのdisplayOuterXmlOfSpecificTag関数は、このメソッドの具体的な使用例です。まずXMLReaderで指定されたXMLファイルを開き、read()メソッドでXMLノードを順番に読み進めます。そして、現在のノードが対象となるタグ名(例えば<book>)の要素であると判断された際に、readOuterXml()を呼び出します。これにより、<book>タグとその全ての子要素を含むXMLブロック全体が文字列として一度に取得され、画面に出力されます。この機能は、大量のXMLデータから特定の構造を持つセクションだけを効率的に抽出し、処理したいシステム開発において非常に有用です。

readOuterXml()メソッドは、現在のXML要素とその全ての子要素を含むXML文字列を返しますが、処理失敗時にはfalseが返されるため、必ずこの戻り値をチェックし、適切にエラー処理を行ってください。このメソッドを呼び出すと、XMLの読み取り位置は現在の要素の終了タグを越えて自動的に進みます。そのため、一度取得した要素に対して再度readOuterXml()を呼び出しても、期待通りの結果は得られません。XMLファイルを開く際にはopen()メソッドの成否を確認し、処理後は必ずclose()メソッドでXMLリーダーのリソースを解放することが重要です。これらの点に留意することで、XML処理を安全かつ効率的に行えます。

PHP 8: XMLノード外側XMLをreadonlyで取得する

1<?php
2
3declare(strict_types=1);
4
5/**
6 * XMLデータを読み込み、特定のノードの外側XMLを取得するクラス。
7 * PHP 8.1で導入されたreadonlyプロパティを使用し、一度設定されたXMLデータが変更されないことを保証します。
8 */
9final class XmlProcessor
10{
11    /**
12     * 処理するXMLデータ。
13     * readonly プロパティは、コンストラクタで初期化された後、値を変更できなくなるため、
14     * オブジェクトの不変性を高めるのに役立ちます。
15     */
16    private readonly string $xmlData;
17
18    /**
19     * コンストラクタ。
20     *
21     * @param string $xmlData 処理するXML文字列。
22     */
23    public function __construct(string $xmlData)
24    {
25        $this->xmlData = $xmlData;
26    }
27
28    /**
29     * XMLデータを順次読み込み、指定されたノードの外側XMLを返します。
30     *
31     * @param string $nodeName 取得したいノードの名前。
32     * @return string|null 取得された外側XML、またはノードが見つからない、もしくはエラーが発生した場合はnull。
33     */
34    public function getOuterXmlForNode(string $nodeName): ?string
35    {
36        // XMLReaderの新しいインスタンスを作成します。
37        $reader = new XMLReader();
38
39        // インメモリのXML文字列をXMLReaderにロードします。
40        // ファイルパスの代わりにXML文字列を直接読み込めます。
41        if (!$reader->xml($this->xmlData)) {
42            // XMLのロードに失敗した場合のエラー処理。
43            error_log("XMLデータのロードに失敗しました。");
44            return null;
45        }
46
47        // XMLを順次読み進めます。
48        while ($reader->read()) {
49            // 現在のノードが要素であり、かつ指定された名前と一致する場合をチェックします。
50            if ($reader->nodeType === XMLReader::ELEMENT && $reader->name === $nodeName) {
51                // 現在のノードとその子ノードを含む、外側のXMLを文字列として取得します。
52                // readOuterXml() は成功すれば文字列、失敗すれば false を返します。
53                $outerXml = $reader->readOuterXml();
54                if ($outerXml === false) {
55                    // 外側XMLの読み込みに失敗した場合のエラー処理。
56                    error_log("ノード '{$nodeName}' の外側XMLの読み込みに失敗しました。");
57                    return null;
58                }
59                // リソースを解放し、結果を返します。
60                $reader->close();
61                return $outerXml;
62            }
63        }
64
65        // 指定されたノードが見つからなかった場合、リソースを解放しnullを返します。
66        $reader->close();
67        return null;
68    }
69}
70
71// サンプルXMLデータ。
72$sampleXml = <<<XML
73<?xml version="1.0" encoding="UTF-8"?>
74<root>
75    <product id="P101">
76        <name>Laptop</name>
77        <price>1200.00</price>
78        <category>Electronics</category>
79    </product>
80    <product id="P102">
81        <name>Mouse</name>
82        <price>25.00</price>
83        <category>Electronics</category>
84    </product>
85    <userPreferences>
86        <theme>dark</theme>
87        <language>en</language>
88    </userPreferences>
89</root>
90XML;
91
92// XmlProcessorのインスタンスを作成します。
93// $sampleXmlはreadonlyプロパティ $xmlData に一度だけ設定され、その後変更されることはありません。
94$processor = new XmlProcessor($sampleXml);
95
96// 'product' ノードの外側XMLを取得してみます。
97echo "--- 'product' ノードの外側XML ---\n";
98$productOuterXml = $processor->getOuterXmlForNode('product');
99if ($productOuterXml !== null) {
100    echo $productOuterXml . "\n\n";
101} else {
102    echo "指定された 'product' ノードが見つかりませんでした、またはエラーが発生しました。\n\n";
103}
104
105// 'userPreferences' ノードの外側XMLを取得してみます。
106echo "--- 'userPreferences' ノードの外側XML ---\n";
107$preferencesOuterXml = $processor->getOuterXmlForNode('userPreferences');
108if ($preferencesOuterXml !== null) {
109    echo $preferencesOuterXml . "\n\n";
110} else {
111    echo "指定された 'userPreferences' ノードが見つかりませんでした、またはエラーが発生しました。\n\n";
112}
113
114// 存在しないノードの外側XMLを取得してみます。
115echo "--- 'nonExistentNode' ノードの外側XML ---\n";
116$nonExistentNodeXml = $processor->getOuterXmlForNode('nonExistentNode');
117if ($nonExistentNodeXml !== null) {
118    echo $nonExistentNodeXml . "\n";
119} else {
120    echo "指定された 'nonExistentNode' ノードは見つかりませんでした。\n";
121}

このPHPサンプルコードは、XMLデータを効率的に読み込み、特定のノードの外側XMLを取得する方法と、PHP 8.1で導入されたreadonlyプロパティの使い方を示しています。

XmlProcessorクラスは、コンストラクタで受け取ったXML文字列をprivate readonly string $xmlDataプロパティに格納します。このreadonlyプロパティは、一度コンストラクタで初期化されると、後からその値を変更できなくする特性を持ち、データの不変性を保証するのに役立ちます。

getOuterXmlForNodeメソッドは、内部でXMLReaderのインスタンスを作成し、保持しているXMLデータを順次読み進めます。指定された$nodeNameの要素が見つかると、XMLReader::readOuterXml()メソッドを呼び出します。このメソッドは引数を取らず、現在のノードの開始タグから終了タグまでを含む、全てのXML文字列を返します。成功した場合は文字列を、失敗した場合はfalseを返すため、サンプルコードではその戻り値をチェックして処理しています。

最終的に、このコードは具体的なXMLデータに対してXmlProcessorクラスを使用し、「product」や「userPreferences」といったノードの外側XMLを抽出して表示することで、XMLReaderの機能とreadonlyプロパティによるデータ管理の利便性を示しています。

XMLReader::readOuterXml()メソッドは、指定されたノードの外側XMLを取得しますが、ノードが見つからなかったり、読み込みに失敗したりした場合にはfalseを返します。nullではなくfalseが返るため、厳密な比較演算子=== falseを使用してエラーを正しく検出することが重要です。XMLReaderはXMLデータを順次読み込むストリームパーサなので、一度読み進めたノードには戻れません。また、処理が終わったら必ずclose()メソッドでリソースを解放してください。

PHP 8.1以降で導入されたreadonlyプロパティは、コンストラクタで一度初期化されると、その後の変更が一切できなくなります。これにより、xmlDataのような重要なデータが誤って変更されることを防ぎ、オブジェクトの不変性を保証することで、コードの信頼性と安全性が向上します。XMLのロード失敗時や目的のノードが見つからない場合のエラーハンドリングを適切に行い、堅牢なアプリケーション開発を心がけてください。

関連コンテンツ

関連IT用語

関連プログラミング言語