PHPでXMLファイルを出力する方法について

採用はこちら

PHPでXMLファイルを出力する方法には、主に次の3つがあります。

  • DOMDocument を使う方法
  • XMLWriter を使う方法
  • 文字列としてXMLを組み立てる方法

この中で、一般的におすすめしやすいのは DOMDocument または XMLWriter です。

DOMDocument は、XMLの構造をオブジェクトとして組み立てられるため、小規模から中規模のXMLを安全に作成したい場合に向いています。

一方、XMLWriter はXMLを順番に書き出していくため、大量のデータを扱う場合や、大きなXMLファイルを生成する場合に便利です。

文字列連結でもXMLは作成できますが、特殊文字のエスケープ漏れや閉じタグのミスが起きやすいため、実務では注意が必要です。

目次

PHPでXMLを出力する基本

PHPでXMLを出力する場合、主に「ブラウザにXMLとして表示する方法」と「XMLファイルとして保存する方法」があります。

ブラウザにXMLとして表示する方法

PHPファイルにアクセスしたとき、ブラウザや外部システムにXMLとして返したい場合は、Content-Type を指定します。

<?php

header('Content-Type: application/xml; charset=UTF-8');

echo '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
echo '<items>' . PHP_EOL;
echo '  <item>' . PHP_EOL;
echo '    <name>商品A</name>' . PHP_EOL;
echo '    <price>1000</price>' . PHP_EOL;
echo '  </item>' . PHP_EOL;
echo '</items>' . PHP_EOL;

ポイントは、header() を出力前に書くことです。

echo やHTML、空白、改行などが先に出力されていると、HTTPヘッダーを正しく送信できない場合があります。

XMLファイルとして保存する方法

XMLをサーバー上にファイルとして保存したい場合は、file_put_contents() を使えます。

<?php

$xml = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
$xml .= '<items>' . PHP_EOL;
$xml .= '  <item>' . PHP_EOL;
$xml .= '    <name>商品A</name>' . PHP_EOL;
$xml .= '    <price>1000</price>' . PHP_EOL;
$xml .= '  </item>' . PHP_EOL;
$xml .= '</items>' . PHP_EOL;

file_put_contents(__DIR__ . '/sample.xml', $xml);

__DIR__ を使うと、現在のPHPファイルが置かれているディレクトリを基準に保存できます。相対パスだけで指定するよりも、保存場所が分かりやすくなります。

ただし、この方法はXMLを文字列として手作業で組み立てるため、データに &< などの特殊文字が含まれる場合は注意が必要です。

DOMDocumentでXMLファイルを出力する方法

PHPでXMLを安全に作成したい場合、まず覚えておきたいのが DOMDocument です。

DOMDocument は、XML文書をツリー構造として作成できるクラスです。

要素、属性、テキストノードを順番に追加していくことで、XMLを組み立てられます。

DOMDocumentの基本コード

以下は、DOMDocument を使ってXMLファイルを作成する基本例です。

<?php

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;

$root = $dom->createElement('items');
$dom->appendChild($root);

$item = $dom->createElement('item');
$root->appendChild($item);

$name = $dom->createElement('name');
$name->appendChild($dom->createTextNode('商品A'));
$item->appendChild($name);

$price = $dom->createElement('price');
$price->appendChild($dom->createTextNode('1000'));
$item->appendChild($price);

$dom->save(__DIR__ . '/sample.xml');

このコードを実行すると、次のようなXMLファイルが作成されます。

<?xml version="1.0" encoding="UTF-8"?>
<items>
  <item>
    <name>商品A</name>
    <price>1000</price>
  </item>
</items>

createTextNodeを使う理由

DOMDocument では、次のように createElement() の第2引数に値を入れることもできます。

$item->appendChild($dom->createElement('name', '商品A'));

固定文字列であれば問題になりにくいですが、実務では商品名、記事タイトル、会社名、説明文などの変数データを入れることが多いです。

そのため、変数の値をXMLに入れる場合は、次のように createTextNode() を使う書き方がおすすめです。

$name = $dom->createElement('name');
$name->appendChild($dom->createTextNode($productName));
$item->appendChild($name);

XMLでは、&< などの文字は特別な意味を持ちます。

たとえば、商品名が A&B商品 のような文字列だった場合、そのままXMLに入れると不正なXMLになる可能性があります。

createTextNode() を使えば、テキストとして扱うべき値を安全に入れやすくなります。

ブラウザにXMLとして出力する方法

DOMDocument で作成したXMLをファイル保存せず、ブラウザに直接出力することもできます。

<?php

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;

$root = $dom->createElement('items');
$dom->appendChild($root);

$item = $dom->createElement('item');
$root->appendChild($item);

$name = $dom->createElement('name');
$name->appendChild($dom->createTextNode('A&B商品'));
$item->appendChild($name);

$price = $dom->createElement('price');
$price->appendChild($dom->createTextNode('1000'));
$item->appendChild($price);

header('Content-Type: application/xml; charset=UTF-8');
echo $dom->saveXML();

このようにすると、PHPにアクセスした際にXMLとしてレスポンスを返せます。

配列データをXMLとして出力する方法

実務では、固定のXMLではなく、配列やデータベースの内容をXMLに変換するケースが多くあります。

たとえば、商品データをXMLとして出力する場合は、次のように書けます。

商品データをXMLに変換する例

<?php

$products = [
    [
        'id' => 1,
        'name' => 'A&B商品',
        'price' => 1000,
        'stock' => 20,
    ],
    [
        'id' => 2,
        'name' => '商品<テスト>',
        'price' => 1500,
        'stock' => 10,
    ],
];

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;

$root = $dom->createElement('products');
$dom->appendChild($root);

foreach ($products as $productData) {
    $product = $dom->createElement('product');
    $product->setAttribute('id', (string) $productData['id']);

    $name = $dom->createElement('name');
    $name->appendChild($dom->createTextNode($productData['name']));
    $product->appendChild($name);

    $price = $dom->createElement('price');
    $price->appendChild($dom->createTextNode((string) $productData['price']));
    $product->appendChild($price);

    $stock = $dom->createElement('stock');
    $stock->appendChild($dom->createTextNode((string) $productData['stock']));
    $product->appendChild($stock);

    $root->appendChild($product);
}

$savePath = __DIR__ . '/products.xml';

if ($dom->save($savePath) === false) {
    throw new RuntimeException('XMLファイルの保存に失敗しました。');
}

出力されるXMLは、次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<products>
  <product id="1">
    <name>A&amp;B商品</name>
    <price>1000</price>
    <stock>20</stock>
  </product>
  <product id="2">
    <name>商品&lt;テスト&gt;</name>
    <price>1500</price>
    <stock>10</stock>
  </product>
</products>

A&B商品& や、商品<テスト>< が、XMLとして正しく扱える形に変換されています。

DOMDocumentを使うメリット

DOMDocument を使うメリットは、XMLの構造を安全に管理できることです。

特に、次のような場合に向いています。

  • XMLの階層構造を分かりやすく作りたい場合
  • 商品データや記事データをXML化したい場合
  • 要素だけでなく属性も使いたい場合
  • 特殊文字を含むデータを扱う場合
  • 小規模から中規模のXMLを作成する場合
  • 後からXMLの構造を修正する可能性がある場合

文字列連結でXMLを作るよりも、タグの閉じ忘れやエスケープ漏れを防ぎやすいのが大きな利点です。

XMLWriterでXMLファイルを出力する方法

大量のデータをXMLとして出力する場合は、XMLWriter が便利です。

DOMDocument はXML全体をメモリ上に構築するため、データ量が多い場合はメモリ使用量が大きくなる可能性があります。

一方、XMLWriter はXMLを順番に書き出していくため、大きなXMLファイルを作成する場合に向いています。

XMLWriterの基本コード

<?php

$writer = new XMLWriter();

if (!$writer->openUri(__DIR__ . '/sample.xml')) {
    throw new RuntimeException('XMLファイルを開けませんでした。');
}

$writer->startDocument('1.0', 'UTF-8');
$writer->setIndent(true);
$writer->setIndentString('  ');

$writer->startElement('items');

$writer->startElement('item');
$writer->writeElement('name', '商品A');
$writer->writeElement('price', '1000');
$writer->endElement();

$writer->endElement();

$writer->endDocument();
$writer->flush();

このコードでは、sample.xml にXMLを直接書き出しています。

XMLWriterで複数データを出力する例

配列の商品データをXMLとして出力する場合は、次のように書けます。

<?php

$products = [
    [
        'id' => 1,
        'name' => 'A&B商品',
        'price' => 1000,
    ],
    [
        'id' => 2,
        'name' => '商品B',
        'price' => 1500,
    ],
];

$writer = new XMLWriter();

if (!$writer->openUri(__DIR__ . '/products.xml')) {
    throw new RuntimeException('XMLファイルを開けませんでした。');
}

$writer->startDocument('1.0', 'UTF-8');
$writer->setIndent(true);
$writer->setIndentString('  ');

$writer->startElement('products');

foreach ($products as $product) {
    $writer->startElement('product');

    $writer->writeAttribute('id', (string) $product['id']);
    $writer->writeElement('name', $product['name']);
    $writer->writeElement('price', (string) $product['price']);

    $writer->endElement();
}

$writer->endElement();

$writer->endDocument();
$writer->flush();

XMLWriterwriteElement() を使うと、要素名と値を指定してXML要素を書き出せます。

XMLWriterでブラウザに出力する方法

ファイルではなく、ブラウザへ直接XMLを返す場合は、openMemory() を使います。

<?php

$writer = new XMLWriter();

$writer->openMemory();

$writer->startDocument('1.0', 'UTF-8');
$writer->setIndent(true);
$writer->setIndentString('  ');

$writer->startElement('items');

$writer->startElement('item');
$writer->writeElement('name', '商品A');
$writer->writeElement('price', '1000');
$writer->endElement();

$writer->endElement();

$writer->endDocument();

header('Content-Type: application/xml; charset=UTF-8');
echo $writer->outputMemory();

XMLWriterを使うメリット

XMLWriter は、大量データを効率よく出力したい場合に向いています。

たとえば、次のようなケースです。

  • 数千件以上の商品データをXML化したい場合
  • 大きなサイトマップXMLを生成したい場合
  • ECサイトの商品フィードを作成したい場合
  • データベースの内容を順番にXML出力したい場合
  • メモリ使用量を抑えたい場合

大量データを扱う場合は、DOMDocument よりも XMLWriter のほうが適していることがあります。

文字列でXMLを作成する方法

簡単なXMLであれば、文字列を連結して作成することもできます。

ただし、文字列でXMLを作る場合は、特殊文字のエスケープを必ず意識する必要があります。

文字列連結でXMLを作る例

<?php

$name = 'A&B商品';
$price = 1000;

$xml = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
$xml .= '<item>' . PHP_EOL;
$xml .= '  <name>' . htmlspecialchars($name, ENT_XML1, 'UTF-8') . '</name>' . PHP_EOL;
$xml .= '  <price>' . htmlspecialchars((string) $price, ENT_XML1, 'UTF-8') . '</price>' . PHP_EOL;
$xml .= '</item>' . PHP_EOL;

file_put_contents(__DIR__ . '/item.xml', $xml, LOCK_EX);

htmlspecialchars()ENT_XML1 を指定することで、XML向けに特殊文字を変換できます。

XMLで注意すべき特殊文字

XMLでは、次のような文字に注意が必要です。

&
<
>
"
'

たとえば、次のような値をそのままXMLに入れると問題になる可能性があります。

$name = 'A&B商品';

XMLでは & は特別な意味を持つため、出力時には次のように変換する必要があります。

<name>A&amp;B商品</name>

文字列でXMLを作る場合は、このようなエスケープ処理を自分で意識しなければなりません。

文字列でXMLを作る場合の注意点

文字列連結は簡単ですが、実務では慎重に使うべき方法です。

特に、次のようなケースでは DOMDocumentXMLWriter を使うほうが安全です。

  • XMLの階層が深い場合
  • データ件数が多い場合
  • ユーザー入力を含む場合
  • データベースの値を出力する場合
  • 外部システムに渡すXMLを作る場合
  • 商品フィードやサイトマップXMLを作る場合

文字列連結では、閉じタグの書き忘れ、属性値のエスケープ漏れ、文字コードの不一致などが起こりやすくなります。

ごく小さく、構造が固定されたXMLを作る場合に限定して使うのがよいでしょう。

XMLファイルをダウンロードさせる方法

XMLをブラウザに表示するのではなく、ファイルとしてダウンロードさせたい場合は、Content-Disposition ヘッダーを指定します。

XMLをダウンロードさせるコード例

<?php

$xml = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
$xml .= '<items>' . PHP_EOL;
$xml .= '  <item>' . PHP_EOL;
$xml .= '    <name>商品A</name>' . PHP_EOL;
$xml .= '    <price>1000</price>' . PHP_EOL;
$xml .= '  </item>' . PHP_EOL;
$xml .= '</items>' . PHP_EOL;

header('Content-Type: application/xml; charset=UTF-8');
header('Content-Disposition: attachment; filename="sample.xml"');

echo $xml;

このように書くと、アクセス時に sample.xml としてダウンロードさせることができます。

ただし、header() の前に何かが出力されていると、ヘッダーが正しく送信されない場合があります。

PHPファイルの先頭に不要な空白や改行が入っていないかも確認しましょう。

サイトマップXMLをPHPで出力する方法

PHPでXMLを出力する実務例として、サイトマップXMLがあります。

サイトマップXMLは、検索エンジンにWebサイト内のURLを伝えるために使われるXMLファイルです。

サイトマップXMLの出力例

<?php

$urls = [
    [
        'loc' => 'https://example.com/',
        'lastmod' => '2026-07-08',
    ],
    [
        'loc' => 'https://example.com/about/',
        'lastmod' => '2026-07-08',
    ],
];

$namespace = 'http://www.sitemaps.org/schemas/sitemap/0.9';

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;

$urlset = $dom->createElementNS($namespace, 'urlset');
$dom->appendChild($urlset);

foreach ($urls as $urlData) {
    $url = $dom->createElementNS($namespace, 'url');

    $loc = $dom->createElementNS($namespace, 'loc');
    $loc->appendChild($dom->createTextNode($urlData['loc']));
    $url->appendChild($loc);

    $lastmod = $dom->createElementNS($namespace, 'lastmod');
    $lastmod->appendChild($dom->createTextNode($urlData['lastmod']));
    $url->appendChild($lastmod);

    $urlset->appendChild($url);
}

header('Content-Type: application/xml; charset=UTF-8');
echo $dom->saveXML();

サイトマップXMLでは、名前空間として次のURLを指定します。

http://www.sitemaps.org/schemas/sitemap/0.9

DOMDocument で名前空間を正確に扱う場合は、createElementNS() を使うとよいでしょう。

サイトマップXMLをファイル保存する場合

ブラウザに出力せず、ファイルとして保存したい場合は、最後を次のように変更します。

$dom->save(__DIR__ . '/sitemap.xml');

定期的にサイトマップを生成したい場合は、管理画面の更新処理やcronなどと組み合わせることもあります。

データベースの内容をXMLに出力する方法

MySQLなどのデータベースから取得したデータをXMLファイルとして出力することもできます。

PDOで取得した商品データをXML化する例

<?php

$pdo = new PDO(
    'mysql:host=localhost;dbname=test_db;charset=utf8mb4',
    'db_user',
    'db_password',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ]
);

$stmt = $pdo->query('SELECT id, name, price FROM products');

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;

$root = $dom->createElement('products');
$dom->appendChild($root);

while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $product = $dom->createElement('product');
    $product->setAttribute('id', (string) $row['id']);

    $name = $dom->createElement('name');
    $name->appendChild($dom->createTextNode($row['name']));
    $product->appendChild($name);

    $price = $dom->createElement('price');
    $price->appendChild($dom->createTextNode((string) $row['price']));
    $product->appendChild($price);

    $root->appendChild($product);
}

$savePath = __DIR__ . '/products.xml';

if ($dom->save($savePath) === false) {
    throw new RuntimeException('XMLファイルの保存に失敗しました。');
}

このように、データベースから取得した値を createTextNode() でXMLに入れることで、特殊文字を含むデータにも対応しやすくなります。

データベース出力で注意すること

データベースの内容をXML化する場合は、次の点に注意しましょう。

  • 文字コードは基本的にUTF-8で統一する
  • ユーザー入力を含む値は安全にテキストノードとして扱う
  • 大量データの場合は XMLWriter の利用も検討する
  • 保存先ディレクトリの書き込み権限を確認する
  • 定期生成する場合は同時書き込みに注意する

商品フィードや記事フィードのように件数が多い場合は、DOMDocument ではなく XMLWriter を使ったほうがメモリ面で有利になることがあります。

XML出力時の文字コード

PHPでXMLを出力する場合、文字コードはUTF-8に統一するのがおすすめです。

UTF-8で統一する

DOMDocument を使う場合は、次のように指定します。

$dom = new DOMDocument('1.0', 'UTF-8');

ブラウザに出力する場合も、HTTPヘッダーでUTF-8を指定します。

header('Content-Type: application/xml; charset=UTF-8');

XML宣言もUTF-8にします。

<?xml version="1.0" encoding="UTF-8"?>

PHPファイル自体もUTF-8で保存しておくと、日本語の文字化けを防ぎやすくなります。

XML出力時によくあるエラー

PHPでXMLを出力する際には、いくつか起こりやすいエラーがあります。

headers already sentが出る

headers already sent は、header() を呼び出す前に何かが出力されているときに起こりやすいエラーです。

悪い例は次のとおりです。

<?php

echo 'test';

header('Content-Type: application/xml; charset=UTF-8');

正しくは、出力より先に header() を書きます。

<?php

header('Content-Type: application/xml; charset=UTF-8');

echo '<?xml version="1.0" encoding="UTF-8"?>';

PHPファイルの先頭や末尾に不要な空白、改行、BOMが入っている場合も原因になることがあります。

XML宣言がPHPタグとして誤解される

XML宣言は次のように始まります。

<?xml version="1.0" encoding="UTF-8"?>

PHPの設定によっては、<?xml がPHPの開始タグのように扱われる可能性があります。

そのため、文字列としてXML宣言を出力する場合は、次のように echo で出力すると安全です。

echo '<?xml version="1.0" encoding="UTF-8"?>';

ただし、DOMDocument を使う場合は、saveXML() でXML宣言を含めたXMLを出力できます。

XMLWriter を使う場合も、startDocument() でXML宣言を出力できます。

特殊文字が原因でXMLが壊れる

XMLでは、&< などの文字に注意が必要です。

たとえば、次のXMLは不正になる可能性があります。

<name>A&B商品</name>

正しくは、次のように出力される必要があります。

<name>A&amp;B商品</name>

DOMDocument では createTextNode() を使い、XMLWriter では writeElement() を使うことで、テキスト値を安全に扱いやすくなります。

文字列連結でXMLを作る場合は、次のように htmlspecialchars() を使います。

htmlspecialchars($value, ENT_XML1, 'UTF-8')

XMLファイルが保存されない

XMLファイルが保存されない場合は、保存先のパスや権限を確認しましょう。

$dom->save(__DIR__ . '/sample.xml');

保存できない主な原因には、次のようなものがあります。

  • 保存先ディレクトリが存在しない
  • PHPから書き込み権限がない
  • 相対パスの基準を誤解している
  • 同名ファイルの上書き権限がない

実務では、保存に失敗した場合の処理も書いておくと安心です。

if ($dom->save(__DIR__ . '/sample.xml') === false) {
    throw new RuntimeException('XMLファイルの保存に失敗しました。');
}

PHPでXMLを出力する方法の使い分け

PHPでXMLを出力する方法は、用途に応じて使い分けることが大切です。

DOMDocumentが向いているケース

DOMDocument は、XMLの構造をしっかり管理したい場合に向いています。

たとえば、次のようなケースです。

  • 小規模から中規模のXMLを作る場合
  • XMLの階層構造を分かりやすく作りたい場合
  • 後から要素や属性を追加・変更したい場合
  • 商品データや記事データをXML化したい場合
  • 特殊文字を含むデータを扱う場合

XMLWriterが向いているケース

XMLWriter は、大量のXMLデータを効率よく書き出したい場合に向いています。

たとえば、次のようなケースです。

  • 数千件以上のデータをXML化する場合
  • 大規模なサイトマップXMLを作る場合
  • ECサイトの商品フィードを作る場合
  • データベースの内容を順番に出力する場合
  • メモリ使用量を抑えたい場合

文字列連結が向いているケース

文字列連結は、ごく小さく構造が固定されたXMLを作る場合に限って使うのがよいでしょう。

たとえば、テスト用の簡単なXMLや、一時的な出力であれば使えます。

ただし、ユーザー入力やデータベースの値を含む場合、また外部システムに渡す重要なXMLを作る場合は、DOMDocumentXMLWriter を使うほうが安全です。

XMLが使われる主な場面

現在のWeb開発ではJSONが使われることも多いですが、XMLが必要になる場面もあります。

サイトマップXML

SEOに関係する代表的なXMLとして、サイトマップXMLがあります。

検索エンジンにURLや更新日を伝えるために使われます。

RSSフィード

ブログやニュースサイトでは、記事情報をRSSフィードとしてXMLで配信することがあります。

商品フィード

ECサイトでは、商品情報を外部サービスに連携するためにXML形式の商品フィードを使う場合があります。

外部システム連携

古い業務システムや取引先のシステムでは、JSONではなくXML形式でのデータ連携が求められることもあります。

SOAP API

SOAP APIでは、XML形式のメッセージを使ってデータをやり取りします。

PHPでXMLを出力するときのポイント

PHPでXMLを出力するときは、次のポイントを押さえておくと安全です。

変数データは安全に出力する

商品名、タイトル、説明文、ユーザー名などの変数データをXMLに入れる場合は、特殊文字に注意しましょう。

DOMDocument を使う場合は createTextNode()、文字列連結の場合は htmlspecialchars() を使うのが基本です。

Content-Typeを正しく指定する

ブラウザや外部システムにXMLとして返す場合は、次のように指定します。

header('Content-Type: application/xml; charset=UTF-8');

HTMLではなくXMLとしてレスポンスを返すことで、受け取る側が正しく処理しやすくなります。

ファイル保存時はパスと権限を確認する

XMLファイルを保存する場合は、保存先のパスと書き込み権限を確認しましょう。

$dom->save(__DIR__ . '/sample.xml');

相対パスでうまく保存できない場合は、__DIR__ を使って保存先を明確にすると分かりやすくなります。

大量データではXMLWriterを検討する

大量のデータをXML化する場合、DOMDocument ではメモリ使用量が大きくなることがあります。

そのような場合は、XMLを順番に書き出せる XMLWriter を使うと効率的です。

まとめ

PHPでXMLファイルを出力する方法には、DOMDocumentXMLWriter、文字列連結があります。

一般的なXMLを安全に作成したい場合は、DOMDocument を使う方法がおすすめです。

XMLの要素や属性をプログラムで組み立てられるため、構造を管理しやすく、特殊文字を含むデータにも対応しやすくなります。

大量のデータをXMLとして出力する場合は、XMLWriter が向いています。

XMLを順番に書き出せるため、大きなXMLファイルや商品フィード、サイトマップXMLなどを作る際に便利です。

文字列連結でもXMLは作れますが、エスケープ漏れや閉じタグのミスが起きやすいため、実務では簡易的な用途に限定するのがよいでしょう。

PHPでXMLを出力するときは、文字コードをUTF-8で統一し、Content-Type を正しく指定し、変数データを安全に扱うことが大切です。

特に、商品名や説明文などに &< が含まれる可能性がある場合は、DOMDocumentcreateTextNode()XMLWriter を活用すると安全にXMLを生成できます。

以上、PHPでXMLファイルを出力する方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次