「XMLを書いていて、タグの中で改行したらちゃんと扱われるの?」
「複数行のテキストを入れたいけど、どう書けばいいの?」
XMLはデータを構造的に管理するのに便利ですが、タグ内の改行やインデントで思わぬ動きをすることもあります。
この記事では、XMLでタグ内を改行するとどう扱われるのか、見た目を整えるインデントのコツ、改行をそのまま保持する方法を初心者向けにわかりやすく解説します。
XMLでの改行と空白の基本ルール
XMLパーサーによる空白の処理
XMLを処理するプログラム(XMLパーサー)は、一般的に以下のルールで空白文字を扱います:
- 連続する空白文字:1つの半角スペースに統合
- 行頭・行末の空白:削除される場合が多い
- タグ間の空白:多くの場合無視される
- 改行文字:半角スペースに変換される場合が多い
空白文字の種類
XMLで扱われる主な空白文字:
文字 | 名称 | Unicode | 説明 |
---|---|---|---|
半角スペース | U+0020 | 最も一般的な空白文字 | |
\t | タブ | U+0009 | インデントによく使用 |
\n | 改行(LF) | U+000A | Unix系の改行文字 |
\r | 復帰(CR) | U+000D | 旧Mac系の改行文字 |
\r\n | CR+LF | – | Windows系の改行文字 |
タグ内での改行の動作
基本的な改行の扱い
例1:タグ内に改行を含む場合
<description>
これは
テストです。
</description>
パーサーでの処理結果
多くのXMLパーサーでは、このデータは以下のように処理されます:
これは テストです。
- 改行文字が半角スペースに変換
- インデントの空白も保持される
例2:より複雑な改行パターン
<poem>
春が来た
春が来た
どこに来た
山に来た
里に来た
野にも来た
</poem>
この場合の処理結果:
春が来た 春が来た どこに来た 山に来た 里に来た 野にも来た
すべての改行が半角スペースに変換されてしまいます。
インデントとフォーマッティング
見た目を整えるインデント
XMLファイルの可読性を高めるために、以下のようなインデントを使用するのは一般的です:
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book id="001">
<title>XMLプログラミング入門</title>
<author>
<name>山田太郎</name>
<nationality>日本</nationality>
</author>
<publisher>技術出版社</publisher>
<price currency="JPY">3200</price>
</book>
<book id="002">
<title>データベース設計の基礎</title>
<author>
<name>佐藤花子</name>
<nationality>日本</nationality>
</author>
<publisher>DB出版</publisher>
<price currency="JPY">2800</price>
</book>
</library>
インデントの推奨方法
スペースを使用(推奨):
- 2スペースまたは4スペースが一般的
- タブ文字よりも環境依存が少ない
一貫性を保つ:
- プロジェクト全体で同じインデント方法を使用
- 自動フォーマッターの活用を検討
改行を確実に保持する方法
方法1:文字実体参照を使用
改行文字の文字実体参照
<message>こんにちは お元気ですか? 今日もいい天気ですね。</message>
主な改行関連の文字実体参照
文字実体参照 | 文字 | 説明 |
---|---|---|
| LF | Unix系の改行 |
| CR | 旧Mac系の改行 |
| CRLF | Windows系の改行 |
実用例
<address>
〒100-0001
東京都千代田区千代田1-1
皇居前ビル3F
</address>
方法2:CDATAセクションを使用
CDATAセクションとは
CDATA(Character Data)セクションは、XML parser が内容を解析せずにそのまま文字データとして扱う領域です。
基本的な書き方
<description>
<![CDATA[
これは複数行の
テキストです。
改行や空白も
そのまま保持されます。
]]>
</description>
CDATAセクションの特徴
メリット:
- 改行や空白がそのまま保持される
- HTMLタグやXMLタグをそのまま書ける
- エスケープ処理が不要
注意点:
]]>
という文字列は使用できない- CDATAセクション内では文字実体参照は使用不可
- ネストはできない
実用例:HTMLコードの格納
<template>
<![CDATA[
<div class="container">
<h1>タイトル</h1>
<p>これは段落です。<br>
改行も含まれています。</p>
</div>
]]>
</template>
実用例:プログラムコードの格納
<code language="javascript">
<![CDATA[
function greet(name) {
console.log("Hello, " + name + "!");
if (name === "World") {
return "Welcome!";
}
return "Nice to meet you!";
}
]]>
</code>
方法3:xml:spaceアトリビュートを使用
xml:spaceアトリビュートとは
XMLの標準的な属性で、空白文字の処理方法を指定できます。
使用方法
<poem xml:space="preserve">
春が来た
春が来た
どこに来た
山に来た
里に来た
野にも来た
</poem>
xml:spaceの値
値 | 説明 |
---|---|
default | 通常の空白処理(デフォルト) |
preserve | 空白をそのまま保持 |
実用例
<document>
<normal-text>この文章では通常の空白処理が適用されます。</normal-text>
<formatted-text xml:space="preserve">
このテキストでは
改行と 空白が
そのまま保持されます。
</formatted-text>
</document>
属性値での改行処理
属性値の制限事項
XMLの属性値では改行を直接記述することはできません。
間違った例
<!-- これはエラーになります -->
<user name="田中
太郎" age="30" />
正しい例
<!-- 改行が必要なデータは要素として記述 -->
<user age="30">
<name>田中
太郎</name>
</user>
属性値で改行を表現したい場合
文字実体参照を使用
<message text="1行目 2行目 3行目" />
ただし、この方法はあまり推奨されません。可読性が悪く、保守が困難になります。
推奨されるアプローチ
<message>
<line>1行目</line>
<line>2行目</line>
<line>3行目</line>
</message>
または
<message>
<![CDATA[1行目
2行目
3行目]]>
</message>
プログラミング言語での処理例
Python での例
import xml.etree.ElementTree as ET
# XMLデータ
xml_data = '''
<document>
<normal>これは
普通のテキストです。</normal>
<with-cdata>
<![CDATA[これは
CDATAセクション内の
テキストです。]]>
</with-cdata>
<with-entity>改行あり テキストです。</with-entity>
</document>
'''
# パース
root = ET.fromstring(xml_data)
# 各要素のテキストを確認
for child in root:
print(f"{child.tag}: '{child.text}'")
print(f"改行文字数: {child.text.count(chr(10))}")
print("---")
実行結果
normal: 'これは
普通のテキストです。'
改行文字数: 1
---
with-cdata: 'これは
CDATAセクション内の
テキストです。'
改行文字数: 2
---
with-entity: '改行あり
テキストです。'
改行文字数: 1
---
JavaScript での例
const xmlString = `
<document>
<message xml:space="preserve">
複数行の
メッセージです。
</message>
</document>
`;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
const messageElement = xmlDoc.querySelector('message');
const text = messageElement.textContent;
console.log("原文:", text);
console.log("改行の数:", (text.match(/\n/g) || []).length);
// 改行を<br>タグに変換してHTMLで表示
const htmlText = text.replace(/\n/g, '<br>');
console.log("HTML形式:", htmlText);
ツール別の改行処理
エディタでの表示
Visual Studio Code
拡張機能「XML Tools」を使用:
- XMLの構文ハイライト
- 自動インデント機能
- CDATAセクションの識別
設定例:
{
"xml.format.enabled": true,
"xml.format.splitAttributes": false,
"xml.format.preserveEmptyContent": true
}
Notepad++
XMLプラグインの活用:
- XML整形機能
- CDATAセクションの色分け
- 改行文字の可視化
ブラウザでの表示
Chrome/Edge
XMLファイルをブラウザで直接開いた場合:
- CDATAセクション内の改行は保持される
- 通常の要素内の改行は無視される場合が多い
Firefox
- より忠実にXMLの改行を表示する傾向
- 開発者ツールでの確認が便利
XMLプロセッサーでの処理
XSLT での処理
<xsl:template match="poem">
<div class="poem">
<xsl:value-of select="." />
</div>
</xsl:template>
改行を保持してHTMLに変換したい場合:
<xsl:template match="poem">
<div class="poem">
<xsl:call-template name="replace-newlines">
<xsl:with-param name="text" select="." />
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="replace-newlines">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, ' ')">
<xsl:value-of select="substring-before($text, ' ')" />
<br />
<xsl:call-template name="replace-newlines">
<xsl:with-param name="text" select="substring-after($text, ' ')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
ベストプラクティス
改行処理の方針決定
プロジェクト開始時に決めること
- 改行の扱い方:
- データとして重要か、単なる見た目か
- 対象システムでの処理方法
- フォーマット規則:
- インデント方法(スペース数、タブの使用可否)
- 要素の配置ルール
- CDATAセクションの使用基準:
- どのようなデータでCDATAを使用するか
- 代替手段との使い分け
推奨されるアプローチ
データ型に応じた選択
短いテキスト(1行程度):
<title>XMLプログラミング入門</title>
複数行だが構造的でないテキスト:
<description xml:space="preserve">
商品説明:
この商品は高品質な素材を使用し、
長期間の使用に耐える設計となっています。
特徴:
- 耐久性抜群
- 環境に優しい
- リーズナブルな価格
</description>
HTMLやコードなどの特殊文字を含むデータ:
<template>
<![CDATA[
<div class="product">
<h2>{{title}}</h2>
<p>{{description}}</p>
<span class="price">${{price}}</span>
</div>
]]>
</template>
構造化されたテキストデータ:
<address>
<postal-code>100-0001</postal-code>
<prefecture>東京都</prefecture>
<city>千代田区</city>
<street>千代田1-1</street>
<building>皇居前ビル3F</building>
</address>
避けるべきパターン
アンチパターン1:属性での複雑なデータ
<!-- 悪い例 -->
<item data="名前:田中太郎 年齢:30 職業:エンジニア" />
<!-- 良い例 -->
<item>
<name>田中太郎</name>
<age>30</age>
<occupation>エンジニア</occupation>
</item>
アンチパターン2:不適切なCDATAの使用
<!-- 悪い例 -->
<price><![CDATA[3000]]></price>
<!-- 良い例 -->
<price>3000</price>
アンチパターン3:一貫性のないフォーマット
<!-- 悪い例 -->
<book>
<title>タイトル1</title>
<author>著者1</author>
<price>1000</price>
</book>
<!-- 良い例 -->
<book>
<title>タイトル1</title>
<author>著者1</author>
<price>1000</price>
</book>
まとめ
XMLでの改行処理のポイント
基本的な理解
- 通常の改行:多くの場合、半角スペースに変換される
- インデント:見た目を整える目的なら自由に使用可能
- データとしての改行:特別な方法で明示的に指定する必要がある
改行を保持する3つの方法
方法 | 使用場面 | メリット | デメリット |
---|---|---|---|
文字実体参照 | 短いテキスト | 軽量、確実 | 可読性が悪い |
CDATAセクション | 長いテキスト、特殊文字 | 自然な書き方 | XMLの利点の一部を放棄 |
xml:space属性 | 標準準拠が重要 | 標準的な方法 | 対応していないパーサーもある |
コメント