XML特殊文字の変換方法を完全解説!エスケープ処理とエンティティ参照の使い方

プログラミング・IT

XMLファイルを作成していて、「<」や「>」をそのまま書いたらエラーになった経験はありませんか?

XMLには特別な意味を持つ文字があり、そのまま使うとファイルが正しく読み込めなくなってしまいます。

この問題を解決するのが「特殊文字の変換」、つまりエスケープ処理です。

この記事では、XMLで特殊文字を扱う方法を、初心者にも分かりやすく解説していきます。

プログラミングをこれから学ぶ方でも理解できるよう、丁寧に説明しますね。

スポンサーリンク

XMLの特殊文字とは?

XMLで特別な意味を持つ文字のことを「特殊文字」または「予約文字」と呼びます。

XMLの5つの予約文字

XMLには、以下の5つの特殊文字があります。

1. < (小なり記号)

  • XMLではタグの開始を意味する
  • 例: <title>

2. > (大なり記号)

  • XMLではタグの終了を意味する
  • 例: </title>

3. & (アンパサンド)

  • XMLではエンティティ参照の開始を意味する
  • 例: &amp;

4. ” (ダブルクォーテーション)

  • XMLでは属性値を囲む記号
  • 例: <item name="test">

5. ‘ (シングルクォーテーション)

  • XMLでは属性値を囲む記号(もう一つの方法)
  • 例: <item name='test'>

なぜ変換が必要なのか?

これらの文字をそのまま使うと、XMLパーサー(XMLを読み込むプログラム)が混乱してしまいます。

問題のある例

<message>3 < 5 は正しい</message>

この場合、XMLパーサーは「<」を新しいタグの開始と勘違いして、エラーになります。

正しい例

<message>3 &lt; 5 は正しい</message>

「<」を「<」に変換することで、XMLパーサーは正しく理解できます。

エンティティ参照による変換方法

エンティティ参照(実体参照)は、特殊文字を別の記号で表現する方法です。

基本的な5つのエンティティ参照

XMLで使える5つのエンティティ参照を覚えましょう。

文字エンティティ参照説明
<&lt;less than(より小さい)
>&gt;greater than(より大きい)
&&amp;ampersand(アンパサンド)
&quot;quotation(引用符)
&apos;apostrophe(アポストロフィ)

エンティティ参照の使い方

例1: 比較演算子を含む文

<description>
  5 &lt; 10 かつ 10 &gt; 5
</description>

これは「5 < 10 かつ 10 > 5」と表示されます。

例2: HTMLタグを文字列として表示

<code>
  画像には&lt;img&gt;タグを使います
</code>

これは「画像にはタグを使います」と表示されます。

例3: アンパサンドを含む文

<company>
  Smith &amp; Co.
</company>

これは「Smith & Co.」と表示されます。

例4: 引用符を含む属性

<item text="彼女は&quot;こんにちは&quot;と言った" />

これは text="彼女は"こんにちは"と言った" と認識されます。

エンティティ参照の書き方ルール

1. 必ず「&」で始まる

すべてのエンティティ参照は「&」(アンパサンド)で始まります。

2. 必ず「;」で終わる

すべてのエンティティ参照は「;」(セミコロン)で終わります。

これを忘れると、正しく変換されません。

3. 大文字と小文字を区別する

&lt; は正しいですが、&LT; はエラーになります。

必ず小文字で書きましょう。

数値文字参照による変換方法

数値文字参照は、Unicodeの文字コードを使って文字を表現する方法です。

10進数表記

文字コードを10進数で指定します。

書き方

&#数値;

  • &#60; → < (文字コード60)
  • &#62; → > (文字コード62)
  • &#38; → & (文字コード38)
  • &#34; → ” (文字コード34)
  • &#39; → ‘ (文字コード39)

16進数表記

文字コードを16進数で指定します。

書き方

&#x16進数;

  • &#x3C; → < (16進数で3C)
  • &#x3E; → > (16進数で3E)
  • &#x26; → & (16進数で26)
  • &#x22; → ” (16進数で22)
  • &#x27; → ‘ (16進数で27)

数値文字参照の使用例

改行コードの表現

<text>
  1行目&#x0D;&#x0A;2行目
</text>

&#x0D; はキャリッジリターン(CR)、&#x0A; はラインフィード(LF)を表します。

特殊な文字の表現

<copyright>
  &#169; 2024 会社名
</copyright>

&#169; は著作権記号©を表します。

CDATAセクションの使用

大量の特殊文字を含むテキストは、CDATAセクションで囲むと便利です。

CDATAセクションとは?

CDATA(Character Data)セクションは、特殊文字をエスケープせずにそのまま書ける領域です。

書き方

<![CDATA[ここに特殊文字を含むテキスト]]>

CDATAセクションの使用例

例1: プログラムコードを含める

<code>
<![CDATA[
if (a < b && c > d) {
    print("条件を満たしました");
}
]]>
</code>

この中では、「<」も「>」も「&」もエスケープ不要です。

例2: HTMLコードを含める

<html-sample>
<![CDATA[
<div class="container">
  <h1>タイトル</h1>
  <p>段落 & 本文</p>
</div>
]]>
</html-sample>

CDATAセクションの注意点

1. ネストできない

CDATAセクションの中に別のCDATAセクションは書けません。

2. 「]]>」は使えない

CDATAセクション内でも「]]>」は終了記号として認識されるため、使用できません。

3. エンティティ参照は展開されない

CDATAセクション内では、&lt; などのエンティティ参照はそのまま文字列として扱われます。

どの方法を使うべき?

状況に応じて、適切な方法を選びましょう。

エンティティ参照を使うべき場合

少数の特殊文字を含む場合

<price>100円 &lt; 200円</price>

1〜2個の特殊文字なら、エンティティ参照が最もシンプルです。

属性値に引用符を含む場合

<item name="&quot;商品A&quot;" />

属性値では、CDATAセクションが使えないため、エンティティ参照を使います。

数値文字参照を使うべき場合

特殊な文字を表現する場合

<symbol>&#169; &#8364; &#9733;</symbol>

©(著作権)、€(ユーロ)、★(星)など、通常のキーボードで入力できない文字を使う時。

改行やタブを明示的に指定する場合

<text>行1&#x0A;行2</text>

CDATAセクションを使うべき場合

大量の特殊文字を含む場合

<script>
<![CDATA[
function test() {
    if (x < 10 && y > 5) {
        alert("OK");
    }
}
]]>
</script>

プログラムコードやHTMLコードなど、特殊文字が多い場合はCDATAが便利です。

各プログラミング言語での実装例

実際のプログラムで、XMLの特殊文字をエスケープする方法を見ていきましょう。

Python

方法1: xml.sax.saxutilsを使う

from xml.sax.saxutils import escape, unescape

# エスケープ
text = "3 < 5 & 5 > 3"
escaped = escape(text)
print(escaped)
# 出力: 3 &lt; 5 &amp; 5 &gt; 3

# アンエスケープ
original = unescape(escaped)
print(original)
# 出力: 3 < 5 & 5 > 3

方法2: html.escapeを使う

import html

text = '<div class="test">テスト</div>'
escaped = html.escape(text)
print(escaped)
# 出力: &lt;div class=&quot;test&quot;&gt;テスト&lt;/div&gt;

JavaScript

方法1: 文字列置換

function escapeXml(text) {
    return text.replace(/[<>"'&]/g, function(char) {
        switch(char) {
            case '<': return '&lt;';
            case '>': return '&gt;';
            case '"': return '&quot;';
            case "'": return '&apos;';
            case '&': return '&amp;';
        }
    });
}

const text = '3 < 5 & 5 > 3';
const escaped = escapeXml(text);
console.log(escaped);
// 出力: 3 &lt; 5 &amp; 5 &gt; 3

方法2: DOMを使う

function escapeXml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

Java

import org.apache.commons.text.StringEscapeUtils;

String text = "3 < 5 & 5 > 3";
String escaped = StringEscapeUtils.escapeXml11(text);
System.out.println(escaped);
// 出力: 3 &lt; 5 &amp; 5 &gt; 3

String original = StringEscapeUtils.unescapeXml(escaped);
System.out.println(original);
// 出力: 3 < 5 & 5 > 3

PHP

$text = "3 < 5 & 5 > 3";
$escaped = htmlspecialchars($text, ENT_XML1, 'UTF-8');
echo $escaped;
// 出力: 3 &lt; 5 &amp; 5 &gt; 3

$original = html_entity_decode($escaped, ENT_XML1, 'UTF-8');
echo $original;
// 出力: 3 < 5 & 5 > 3

C

using System.Security;
using System.Xml;

string text = "3 < 5 & 5 > 3";
string escaped = SecurityElement.Escape(text);
Console.WriteLine(escaped);
// 出力: 3 &lt; 5 &amp; 5 &gt; 3

よくあるエラーと対処法

XMLの特殊文字変換でよく起こる問題と解決方法を紹介します。

エラー1: アンパサンドのエスケープ忘れ

間違った例

<company>Smith & Co.</company>

エラーメッセージ

The reference to entity "Co" must end with the ';' delimiter.

正しい例

<company>Smith &amp; Co.</company>

アンパサンド(&)は必ず&amp;に変換しましょう。

エラー2: 属性値の引用符エスケープ忘れ

間違った例

<item name="彼は"こんにちは"と言った" />

正しい例

<item name="彼は&quot;こんにちは&quot;と言った" />

または

<item name='彼は"こんにちは"と言った' />

属性値を囲む引用符と異なる引用符を使えば、エスケープ不要です。

エラー3: セミコロンの忘れ

間違った例

<text>3 &lt 5</text>

正しい例

<text>3 &lt; 5</text>

エンティティ参照は必ずセミコロン(;)で終わります。

エラー4: 二重エスケープ

間違った例

<text>3 &amp;lt; 5</text>

これは「3 < 5」と表示されてしまいます。

正しい例

<text>3 &lt; 5</text>

一度だけエスケープすれば十分です。

エラー5: CDATAセクション内でのエスケープ

不要なエスケープの例

<code>
<![CDATA[
if (x &lt; 10) {
    // 処理
}
]]>
</code>

CDATAセクション内では、&lt;はそのまま文字列として扱われます。

正しい例

<code>
<![CDATA[
if (x < 10) {
    // 処理
}
]]>
</code>

CDATAセクション内では、エスケープ不要です。

実践的な使用例

実際のXML文書での使用例を見ていきましょう。

例1: ブログ記事のXML

<?xml version="1.0" encoding="UTF-8"?>
<blog>
  <article>
    <title>HTMLの基礎 &amp; タグの使い方</title>
    <author>山田太郎</author>
    <content>
      <![CDATA[
      <p>HTMLでは、段落を表すのに<p>タグを使います。</p>
      <p>条件式 (x < 10 && y > 5) のような記号も書けます。</p>
      ]]>
    </content>
    <summary>
      段落には&lt;p&gt;タグを使用し、条件式では &lt; や &gt; を使います。
    </summary>
  </article>
</blog>

例2: 商品カタログのXML

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <product id="001">
    <name>シャンプー &amp; コンディショナーセット</name>
    <price currency="JPY">1500</price>
    <description>
      髪に優しい成分配合
      容量: 300ml &times; 2本
    </description>
    <note>価格は税込です。&#169; 2024 会社名</note>
  </product>

  <product id="002">
    <name xml:lang="en">Smith &amp; Co. Soap</name>
    <condition>新品 &quot;未開封&quot;</condition>
    <spec formula="3 &lt; pH &lt; 7">弱酸性</spec>
  </product>
</catalog>

例3: 設定ファイルのXML

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <database>
    <connection>
      server=localhost;database=test
    </connection>
    <query>
      <![CDATA[
      SELECT * FROM users 
      WHERE age > 18 AND status = 'active'
      ORDER BY created_at DESC
      ]]>
    </query>
  </database>

  <messages>
    <error code="404">
      ページが見つかりません。
      詳細: &lt;エラーコード: 404&gt;
    </error>
    <success>
      処理が完了しました &#10004;
    </success>
  </messages>
</config>

よくある質問

Q1: すべての特殊文字をエスケープする必要がありますか?

A: いいえ、状況によります。要素の内容では「<」と「&」のエスケープが必須ですが、「>」は必須ではありません。ただし、安全のため全てエスケープすることを推奨します。

Q2: シングルクォートとダブルクォートはどちらを使うべきですか?

A: どちらでも構いませんが、属性値を囲む引用符と異なる方を使えば、内部の引用符はエスケープ不要です。

Q3: 数値文字参照とエンティティ参照、どちらが良いですか?

A: 基本的な5つの文字(<, >, &, “, ‘)にはエンティティ参照を使い、それ以外の特殊文字には数値文字参照を使うのが一般的です。

Q4: XMLコメント内でも特殊文字をエスケープする必要がありますか?

A: いいえ、XMLコメント()内では特殊文字をエスケープする必要はありません。ただし、「–」という連続するハイフンは使用できません。

Q5: CDATAセクションの中にCDATAセクションを入れられますか?

A: いいえ、CDATAセクションはネストできません。内部のCDATAセクションは終了タグ「]]>」で外側のCDATAセクションも終了してしまいます。

Q6: プログラムで自動的にエスケープする方法はありますか?

A: はい、ほとんどのプログラミング言語には、XMLの特殊文字を自動的にエスケープするライブラリや関数が用意されています。

Q7: HTMLのエスケープとXMLのエスケープは同じですか?

A: 基本的には同じですが、HTMLには&nbsp;(ノーブレークスペース)など、XML標準にはないエンティティ参照があります。

Q8: 改行コードはエスケープが必要ですか?

A: 通常の改行は不要ですが、属性値内では改行をそのまま入れると問題が起こる場合があります。その場合は&#x0A;を使います。

Q9: エスケープを忘れるとどうなりますか?

A: XMLパーサーがエラーを出して、ファイルを正しく読み込めません。Webアプリケーションでは、XSS(クロスサイトスクリプティング)などのセキュリティ問題につながることもあります。

Q10: 自動生成ツールを使えばエスケープは不要ですか?

A: XMLを自動生成するライブラリやツールを使えば、通常は自動的にエスケープしてくれます。しかし、手動でXMLを編集する場合は注意が必要です。

まとめ

XMLの特殊文字変換について解説しました。

重要なポイント

5つの予約文字

  • <&lt;
  • >&gt;
  • &&amp;
  • "&quot;
  • '&apos;

変換方法の選択

  • 少数の特殊文字 → エンティティ参照
  • 特殊な文字 → 数値文字参照
  • 大量の特殊文字 → CDATAセクション

エンティティ参照のルール

  • 必ず&で始まる
  • 必ず;で終わる
  • 小文字で書く

よくあるミス

  • アンパサンド(&)のエスケープ忘れ
  • セミコロン(;)の忘れ
  • 二重エスケープ
  • CDATA内での不要なエスケープ

実装のポイント

  • プログラミング言語のライブラリを活用
  • 手動編集時は特に注意
  • セキュリティ面でも重要

XMLの特殊文字変換は、一見難しそうに見えますが、基本的なルールを理解すれば簡単です。

エンティティ参照、数値文字参照、CDATAセクションを適切に使い分けて、正しいXMLファイルを作成しましょう!

コメント

タイトルとURLをコピーしました