XMLでダブルクォーテーションをエスケープする方法|正しい書き方と注意点

Web

「XMLにテキストデータを入れたらエラーになった…」
「文字列にダブルクォーテーション(“)が入ってるけど、これどうやって書けばいいの?」

こんな経験はありませんか?

XMLでは、タグや属性を使ってデータを表現するため、一部の記号は「エスケープ」して書く必要があります。特にダブルクォーテーション(“)は属性でよく使うため、正しく扱わないとXMLパーサーがエラーを返してしまいます。

この記事では、以下について初心者向けにわかりやすく解説します:

  • XMLでのダブルクォーテーションの正しいエスケープ方法
  • よく使うエスケープ文字一覧
  • 実際の使用場面と注意すべきポイント
スポンサーリンク

XMLでエスケープが必要な理由

XMLの構文ルール

XMLは構造化されたデータを表現するための言語で、以下のような記号が特別な意味を持ちます:

  • <> はタグを区切る記号
  • "(ダブルクォーテーション)は属性値を囲む記号
  • & はエスケープシーケンスの開始記号

そのため、これらの記号をデータとしてそのまま書いてしまうと、XMLパーサー(読み込みソフト)が「これはタグの一部なのか?データなのか?」と混乱してしまいます。

具体的な問題例

エラーになる例

<message>彼は "OK" と言った。</message>

この場合、属性値ではないのでエラーにならない場合もありますが、以下のような属性では確実にエラーになります:

<!-- これはエラーになる -->
<user comment="彼は "OK" と答えた" />

XMLパーサーは最初の " で属性値が始まり、次の " で属性値が終わったと判断してしまいます。

正しい例

<user comment="彼は &quot;OK&quot; と答えた" />

XMLでダブルクォーテーションをエスケープする方法

実体参照(Entity Reference)を使う

XMLでは &quot; という実体参照を使って、ダブルクォーテーション(“)をエスケープできます。

基本的な使い方

<message>彼は &quot;こんにちは&quot; と言った。</message>

この例では、XMLパーサーは &quot;" という文字として正しく解釈し、"こんにちは" を単なる文字列データとして扱います。

表示結果

上記のXMLを読み込むと、実際のデータは以下のようになります:

彼は "こんにちは" と言った。

属性値でのエスケープ

属性値の中でダブルクォーテーションを使いたい場合は、必ずエスケープが必要です。

基本パターン

<product n="スマートフォン &quot;Galaxy&quot;" price="89800" />
<book title="&quot;ハリー・ポッター&quot; 第1巻" author="J.K.ローリング" />

複雑な例

<review>
    <comment rating="5">
        この商品は &quot;最高&quot; です!
        友人も &quot;素晴らしい&quot; と言っていました。
    </comment>
    <quote author="田中さん">
        &quot;買って良かった&quot; と心から思います。
    </quote>
</review>

要素内容でのエスケープ

要素の内容(テキストノード)では、ダブルクォーテーションをそのまま書いても構文エラーにはなりませんが、一貫性と安全性のためにエスケープすることを推奨します。

エスケープあり(推奨)

<dialog>
    <speaker>太郎</speaker>
    <message>彼女は &quot;ありがとう&quot; と言った。</message>
</dialog>

エスケープなし(動作するが非推奨)

<dialog>
    <speaker>太郎</speaker>
    <message>彼女は "ありがとう" と言った。</message>
</dialog>

よく使うXMLのエスケープ文字一覧

必須エスケープ文字

XMLで特別な意味を持つ文字は、以下のようにエスケープします:

文字実体参照説明使用場面
<&lt;小なり記号タグの開始と区別するため
>&gt;大なり記号タグの終了と区別するため
&&amp;アンパサンドエスケープ文字と区別するため
"&quot;ダブルクォーテーション属性値の区切りと区別するため
'&apos;シングルクォーテーション属性値の区切りと区別するため

実際の使用例

<?xml version="1.0" encoding="UTF-8"?>
<document>
    <title>XMLエスケープの &amp; 実体参照について</title>
    
    <section>
        <h>比較演算子の使い方</h>
        <content>
            if (x &lt; 10 &amp;&amp; y &gt; 5) { ... }
        </content>
    </section>
    
    <quote author="開発者A">
        &quot;XMLは &apos;構造化データ&apos; を表現するのに最適&quot;
    </quote>
    
    <message type="info" text="処理が &quot;成功&quot; しました" />
</document>

数値文字参照も使用可能

実体参照の代わりに、数値文字参照も使えます:

文字10進数16進数
"&#34;&#x22;
'&#39;&#x27;
<&#60;&#x3C;
>&#62;&#x3E;
&&#38;&#x26;

数値文字参照の例

<message>彼は &#34;こんにちは&#34; と言った。</message>

よくある間違いと注意点

エスケープを忘れる

間違った例

<!-- エラーになる -->
<user comment="彼は "OK" と言った" />

<!-- エラーになる -->
<formula>if (x < 10 && y > 5)</formula>

正しい例

<user comment="彼は &quot;OK&quot; と言った" />
<formula>if (x &lt; 10 &amp;&amp; y &gt; 5)</formula>

エスケープのし忘れによるセキュリティ問題

XMLをWebアプリケーションで使用する場合、エスケープを忘れるとXMLインジェクション攻撃の原因になる可能性があります。

危険な例

<!-- ユーザー入力をそのまま埋め込むと危険 -->
<user comment="{user_input}" />

安全な例

<!-- ユーザー入力を適切にエスケープ -->
<user comment="ユーザーは &quot;Hello &amp; Goodbye&quot; と入力しました" />

属性値でのシングルクォーテーションとダブルクォーテーション

XMLでは属性値をシングルクォーテーションで囲むこともできます。この場合、内部のダブルクォーテーションはエスケープ不要です。

パターン1: ダブルクォーテーションで囲む場合

<element attr="内部の &quot;テキスト&quot; です" />

パターン2: シングルクォーテーションで囲む場合

<element attr='内部の "テキスト" です' />

パターン3: 両方を含む場合

<element attr="He said &quot;It&apos;s great!&quot;" />

プログラミング言語でのエスケープ処理

Pythonでの例

import xml.etree.ElementTree as ET
import html

# 手動でエスケープ
def escape_xml(text):
    return (text.replace('&', '&amp;')
                .replace('<', '&lt;')
                .replace('>', '&gt;')
                .replace('"', '&quot;')
                .replace("'", '&apos;'))

# ライブラリを使用(推奨)
text = 'He said "Hello & Goodbye"'
escaped = html.escape(text, quote=True)
print(escaped)  # He said &quot;Hello &amp; Goodbye&quot;

# ElementTreeを使用した安全な方法
root = ET.Element("message")
root.text = 'He said "Hello & Goodbye"'
print(ET.tostring(root, encoding='unicode'))

JavaScriptでの例

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

// 使用例
const userInput = 'He said "Hello & Goodbye"';
const safeXml = `<message>${escapeXml(userInput)}</message>`;
console.log(safeXml);

CDATAセクションという代替手段

エスケープが面倒な場合は、CDATAセクションを使う方法もあります。

CDATAの基本構文

<![CDATA[ここに書いた内容はエスケープ不要]]>

CDATAの使用例

<code>
<![CDATA[
if (x < 10 && y > 5) {
    console.log("条件に一致しました");
    return "success";
}
]]>
</code>

CDATAの注意点

CDATAセクション内では以下の制限があります:

  • ]]> という文字列は使用できない
  • XMLの構造は解析されない(タグも文字として扱われる)
  • 属性値には使用できない

XMLバリデーションでのエラーチェック

よくあるエラーメッセージ

エスケープ忘れのエラー

Error: The reference to entity "OK" must end with the ';' delimiter.

このエラーは、"OK" の部分でエスケープが不適切な場合に発生します。

解決方法

<!-- エラーの原因 -->
<message text="He said "OK"" />

<!-- 正しい書き方 -->
<message text="He said &quot;OK&quot;" />

XMLリンターやバリデーターの活用

オンラインツール

  • W3C Markup Validator
  • XMLint(XMLlint オンライン版)
  • FreeFormatter XML Validator

エディタの機能

  • Visual Studio Code: XML拡張機能
  • IntelliJ IDEA: 内蔵XML validator
  • Notepad++: XMLツールプラグイン

まとめ

今回は「XMLでダブルクォーテーションをエスケープする方法」について詳しく解説しました。

重要なポイント:

  • XMLでダブルクォーテーションは &quot; でエスケープする
  • 属性値内では必ずエスケープが必要
  • 要素内容では必須ではないが、一貫性のためエスケープを推奨
  • <>&"' の5つの文字は適切にエスケープする
  • プログラムで扱う場合は、専用ライブラリの使用を推奨
  • CDATAセクションも代替手段として有効

コメント

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