「XMLで同じ要素を繰り返し書きたいけど、どうすればいいの?」
「商品リストやユーザーリストをXMLで表現する方法が分からない…」
XMLでデータを扱っていると、リストや一覧のように「同じ構造を繰り返す」場面が必ずありますよね。でも、XMLには「繰り返し」を表す特別な構文はありません。
この記事では、XMLで繰り返し構造を表現する方法について、基本から実践的な使い方まで詳しく解説していきます。プログラミング言語での処理方法も紹介するので、実務でもすぐに活用できますよ。
XMLの繰り返しとは?
まず、XMLにおける「繰り返し」の概念から説明しますね。
繰り返しの基本的な考え方
XMLでは、同じ名前の要素を複数回記述することで、繰り返し構造を表現します。
イメージ:
<books>
<book>本A</book>
<book>本B</book>
<book>本C</book>
</books>
このように、同じ<book>要素を何度でも記述できるんです。
プログラミング言語の配列・リストとの対応
プログラミングに慣れている方なら、配列やリストをイメージすると分かりやすいでしょう。
JavaScript配列との比較:
// JavaScript
const books = ["本A", "本B", "本C"];
これがXMLだと:
<books>
<book>本A</book>
<book>本B</book>
<book>本C</book>
</books>
構造は似ていますが、XMLの方が階層構造を表現しやすいですね。
基本的な繰り返しの書き方
具体的な記述方法を見ていきましょう。
パターン1:単純な値の繰り返し
最もシンプルな繰り返しです。
構文:
<親要素>
<子要素>値1</子要素>
<子要素>値2</子要素>
<子要素>値3</子要素>
</親要素>
実例:
<!-- 商品名のリスト -->
<products>
<product>ノートPC</product>
<product>マウス</product>
<product>キーボード</product>
</products>
<!-- タグのリスト -->
<tags>
<tag>技術</tag>
<tag>プログラミング</tag>
<tag>XML</tag>
</tags>
親要素で全体をまとめ、子要素を繰り返すのが基本です。
パターン2:複数の子要素を持つ繰り返し
各項目が複数の情報を持つ場合です。
構文:
<親要素>
<項目>
<子要素1>値</子要素1>
<子要素2>値</子要素2>
</項目>
<項目>
<子要素1>値</子要素1>
<子要素2>値</子要素2>
</項目>
</親要素>
実例:
<!-- ユーザー情報のリスト -->
<users>
<user>
<id>1</id>
<name>山田太郎</name>
<email>yamada@example.com</email>
</user>
<user>
<id>2</id>
<name>佐藤花子</name>
<email>sato@example.com</email>
</user>
<user>
<id>3</id>
<name>鈴木一郎</name>
<email>suzuki@example.com</email>
</user>
</users>
これが実務で最もよく使われるパターンですね。
パターン3:属性を使った繰り返し
属性を組み合わせることもできます。
実例:
<products>
<product id="1" category="electronics">
<name>ノートPC</name>
<price>120000</price>
</product>
<product id="2" category="electronics">
<name>マウス</name>
<price>2500</price>
</product>
<product id="3" category="office">
<name>ボールペン</name>
<price>150</price>
</product>
</products>
識別子やカテゴリなど、短い情報は属性で表現すると便利です。
実践的な繰り返しの例
実際の開発でよく使われる例を紹介します。
例1:商品カタログ
ECサイトの商品リストのイメージです。
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<product>
<id>P001</id>
<name>スマートフォン X</name>
<price currency="JPY">89800</price>
<stock>25</stock>
<category>Electronics</category>
<description>最新モデルのスマートフォン</description>
</product>
<product>
<id>P002</id>
<name>ワイヤレスイヤホン</name>
<price currency="JPY">15800</price>
<stock>100</stock>
<category>Audio</category>
<description>高音質ワイヤレスイヤホン</description>
</product>
<product>
<id>P003</id>
<name>タブレット端末</name>
<price currency="JPY">45000</price>
<stock>0</stock>
<category>Electronics</category>
<description>10インチタブレット</description>
</product>
</catalog>
商品ごとに同じ構造を繰り返しています。
例2:ブログ記事のリスト
ブログのRSSフィードをイメージした例です。
<?xml version="1.0" encoding="UTF-8"?>
<blog>
<posts>
<post>
<title>XMLの基礎を学ぶ</title>
<author>山田太郎</author>
<date>2024-11-01</date>
<category>技術</category>
<tags>
<tag>XML</tag>
<tag>プログラミング</tag>
<tag>基礎</tag>
</tags>
<content>
XMLの基本的な書き方について解説します...
</content>
</post>
<post>
<title>データベース設計のコツ</title>
<author>佐藤花子</author>
<date>2024-11-05</date>
<category>データベース</category>
<tags>
<tag>Database</tag>
<tag>設計</tag>
</tags>
<content>
効率的なデータベース設計の方法を紹介...
</content>
</post>
</posts>
</blog>
記事の中にタグのリスト(繰り返しの入れ子)も含まれています。
例3:住所録
連絡先情報のリストです。
<?xml version="1.0" encoding="UTF-8"?>
<addressBook>
<contact>
<name>
<first>太郎</first>
<last>山田</last>
</name>
<phones>
<phone type="mobile">090-1234-5678</phone>
<phone type="home">03-1234-5678</phone>
</phones>
<address>
<zip>100-0001</zip>
<prefecture>東京都</prefecture>
<city>千代田区</city>
<street>千代田1-1-1</street>
</address>
</contact>
<contact>
<name>
<first>花子</first>
<last>佐藤</last>
</name>
<phones>
<phone type="mobile">080-9876-5432</phone>
</phones>
<address>
<zip>150-0001</zip>
<prefecture>東京都</prefecture>
<city>渋谷区</city>
<street>渋谷2-2-2</street>
</address>
</contact>
</addressBook>
連絡先ごとに複数の電話番号を持つなど、複雑な繰り返し構造も表現できます。
例4:レストランのメニュー
飲食店のメニューリストです。
<?xml version="1.0" encoding="UTF-8"?>
<menu>
<section name="前菜">
<item>
<name>サラダ</name>
<price>800</price>
<vegetarian>true</vegetarian>
</item>
<item>
<name>カルパッチョ</name>
<price>1200</price>
<vegetarian>false</vegetarian>
</item>
</section>
<section name="メイン">
<item>
<name>ステーキ</name>
<price>2800</price>
<vegetarian>false</vegetarian>
</item>
<item>
<name>パスタ</name>
<price>1500</price>
<vegetarian>true</vegetarian>
</item>
</section>
<section name="デザート">
<item>
<name>ティラミス</name>
<price>600</price>
<vegetarian>true</vegetarian>
</item>
</section>
</menu>
セクション(カテゴリ)ごとにメニュー項目を繰り返す構造です。
ネストした繰り返し(入れ子構造)
繰り返しの中に、さらに繰り返しを含めることもできます。
基本的な入れ子構造
例:カテゴリと商品
<categories>
<category name="電化製品">
<product>テレビ</product>
<product>冷蔵庫</product>
<product>洗濯機</product>
</category>
<category name="家具">
<product>ソファ</product>
<product>テーブル</product>
<product>椅子</product>
</category>
</categories>
カテゴリが繰り返され、その中で商品も繰り返されています。
より複雑な入れ子構造
例:学校のクラスと生徒
<school>
<grade level="1">
<class name="A組">
<student id="101">
<name>山田太郎</name>
<scores>
<subject name="国語">85</subject>
<subject name="数学">92</subject>
<subject name="英語">78</subject>
</scores>
</student>
<student id="102">
<name>佐藤花子</name>
<scores>
<subject name="国語">90</subject>
<subject name="数学">88</subject>
<subject name="英語">95</subject>
</scores>
</student>
</class>
<class name="B組">
<student id="201">
<name>鈴木一郎</name>
<scores>
<subject name="国語">75</subject>
<subject name="数学">80</subject>
<subject name="英語">82</subject>
</scores>
</student>
</class>
</grade>
</school>
学年 → クラス → 生徒 → 科目と、4階層の繰り返しが入れ子になっています。
プログラミング言語での処理方法
XMLの繰り返しをプログラムで処理する方法を見ていきましょう。
JavaScript(DOMParser)
XMLの読み込みと繰り返し処理:
// XMLテキスト
const xmlText = `
<products>
<product>
<name>商品A</name>
<price>1000</price>
</product>
<product>
<name>商品B</name>
<price>2000</price>
</product>
</products>
`;
// XMLをパース
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
// product要素を全て取得
const products = xmlDoc.getElementsByTagName("product");
// 繰り返し処理
for (let i = 0; i < products.length; i++) {
const name = products[i].getElementsByTagName("name")[0].textContent;
const price = products[i].getElementsByTagName("price")[0].textContent;
console.log(`商品: ${name}, 価格: ${price}円`);
}
Python(xml.etree.ElementTree)
XMLの読み込みと繰り返し処理:
import xml.etree.ElementTree as ET
# XMLテキスト
xml_text = """
<products>
<product>
<name>商品A</name>
<price>1000</price>
</product>
<product>
<name>商品B</name>
<price>2000</price>
</product>
</products>
"""
# XMLをパース
root = ET.fromstring(xml_text)
# product要素を繰り返し処理
for product in root.findall('product'):
name = product.find('name').text
price = product.find('price').text
print(f'商品: {name}, 価格: {price}円')
PHP(SimpleXML)
XMLの読み込みと繰り返し処理:
<?php
// XMLテキスト
$xmlText = <<<XML
<products>
<product>
<name>商品A</name>
<price>1000</price>
</product>
<product>
<name>商品B</name>
<price>2000</price>
</product>
</products>
XML;
// XMLをパース
$xml = simplexml_load_string($xmlText);
// product要素を繰り返し処理
foreach ($xml->product as $product) {
$name = $product->name;
$price = $product->price;
echo "商品: $name, 価格: {$price}円\n";
}
?>
Java(DOM)
XMLの読み込みと繰り返し処理:
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
// XMLテキスト
String xmlText = "<products>" +
"<product><name>商品A</name><price>1000</price></product>" +
"<product><name>商品B</name><price>2000</price></product>" +
"</products>";
// XMLをパース
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(
new ByteArrayInputStream(xmlText.getBytes())
);
// product要素を全て取得
NodeList products = doc.getElementsByTagName("product");
// 繰り返し処理
for (int i = 0; i < products.getLength(); i++) {
Element product = (Element) products.item(i);
String name = product.getElementsByTagName("name")
.item(0).getTextContent();
String price = product.getElementsByTagName("price")
.item(0).getTextContent();
System.out.println("商品: " + name + ", 価格: " + price + "円");
}
どの言語でも、基本的な処理の流れは同じですね。
XPathでの繰り返し要素の取得
XPath(XML Path Language)を使うと、より柔軟に要素を取得できます。
基本的なXPath式
全ての要素を取得:
//product
特定の親の下の要素を取得:
/products/product
条件付きで取得:
//product[price > 1000]
JavaScript with XPath
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
// XPathで要素を取得
const xpath = "//product[price > 1000]";
const result = xmlDoc.evaluate(
xpath,
xmlDoc,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
// 結果を繰り返し処理
for (let i = 0; i < result.snapshotLength; i++) {
const node = result.snapshotItem(i);
const name = node.getElementsByTagName("name")[0].textContent;
console.log(name);
}
XPathを使うと、複雑な条件でも簡潔に記述できます。
XSLTでの繰り返し処理
XSLT(XSL Transformations)を使うと、XMLを変換できます。
基本的なXSLT繰り返し
XML:
<products>
<product>
<name>商品A</name>
<price>1000</price>
</product>
<product>
<name>商品B</name>
<price>2000</price>
</product>
</products>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>商品リスト</h1>
<ul>
<xsl:for-each select="products/product">
<li>
<xsl:value-of select="name"/>
- <xsl:value-of select="price"/>円
</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
出力結果(HTML):
<html>
<body>
<h1>商品リスト</h1>
<ul>
<li>商品A - 1000円</li>
<li>商品B - 2000円</li>
</ul>
</body>
</html>
XSLTの<xsl:for-each>を使って繰り返し処理ができます。
繰り返しの書き方:ベストプラクティス
より良いXMLを書くためのポイントをまとめます。
1. 適切な要素名を使う
良い例:
<users>
<user>
<name>山田太郎</name>
</user>
</users>
悪い例:
<data>
<item>
<value>山田太郎</value>
</item>
</data>
意味のある要素名を使いましょう。
2. 親要素で複数形、子要素で単数形
推奨パターン:
<books> <!-- 複数形 -->
<book> <!-- 単数形 -->
...
</book>
</books>
この命名規則は多くのXML設計で採用されています。
3. 深すぎる入れ子を避ける
適度な深さ:
<categories>
<category>
<products>
<product>...</product>
</products>
</category>
</categories>
深すぎる例(避けるべき):
<level1>
<level2>
<level3>
<level4>
<level5>
<level6>...</level6>
</level5>
</level4>
</level3>
</level2>
</level1>
5階層以上の入れ子は、可能な限り避けましょう。
4. 属性と要素の使い分け
属性を使うべき:
- ID、コード、カテゴリなど短い識別子
- メタデータ
要素を使うべき:
- 複数行になる可能性のあるデータ
- 構造化されたデータ
- 繰り返しが必要なデータ
例:
<product id="P001" category="electronics">
<name>ノートPC</name>
<description>
高性能なノートパソコン。
最新のCPUを搭載。
</description>
</product>
5. 一貫性のある構造
同じ種類のデータは、常に同じ構造で記述しましょう。
良い例:
<users>
<user>
<id>1</id>
<name>山田太郎</name>
</user>
<user>
<id>2</id>
<name>佐藤花子</name>
</user>
</users>
悪い例:
<users>
<user id="1">山田太郎</user>
<user>
<id>2</id>
<name>佐藤花子</name>
</user>
</users>
統一された構造の方が処理しやすいです。
よくある間違いと対処法
XMLの繰り返しでよくある間違いを紹介します。
間違い1:親要素なしで繰り返す
間違い:
<product>商品A</product>
<product>商品B</product>
<product>商品C</product>
XMLでは、必ず1つのルート要素が必要です。
正しい書き方:
<products>
<product>商品A</product>
<product>商品B</product>
<product>商品C</product>
</products>
間違い2:タグの閉じ忘れ
間違い:
<products>
<product>商品A
<product>商品B</product>
</products>
正しい書き方:
<products>
<product>商品A</product>
<product>商品B</product>
</products>
全てのタグは必ず閉じる必要があります。
間違い3:不正な文字の使用
間違い:
<product>
<price>100 < 200</price>
</product>
<や&などの特殊文字はエスケープが必要です。
正しい書き方:
<product>
<price>100 < 200</price>
</product>
または、CDATAセクションを使います:
<product>
<description><![CDATA[価格は100 < 200です]]></description>
</product>
間違い4:エンコーディングの不一致
間違い:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ファイルがShift_JISで保存されている -->
<products>
<product>商品A</product>
</products>
宣言と実際のファイルエンコーディングを一致させましょう。
よくある質問と回答
Q1. XMLで配列のインデックスは使える?
A. XMLには配列のインデックスという概念はありません。ただし、属性で順序を表現することはできます。
<items>
<item index="0">最初</item>
<item index="1">2番目</item>
<item index="2">3番目</item>
</items>
ただし、通常はXML内の要素の順序がそのまま順番を表します。
Q2. 空の繰り返しはどう書く?
A. 要素がない場合は、親要素だけを記述します。
<!-- 商品がない場合 -->
<products></products>
<!-- または自己閉じタグ -->
<products/>
Q3. 繰り返しの数に制限はある?
A. XML仕様上は制限はありませんが、実際には以下の制限があります:
- パーサーのメモリ制限
- ファイルサイズの制限
- 処理時間の制約
実務では、数万件程度までは問題なく扱えますが、それ以上になる場合は分割を検討しましょう。
Q4. JSONとXML、どちらが繰り返しに適している?
A. 用途によります。
- JSON: Webアプリケーション、軽量なデータ交換
- XML: 複雑な構造、文書指向、厳密なバリデーションが必要な場合
XMLは属性や名前空間など、より豊富な機能を持っています。
Q5. 繰り返しの中で順序は保証される?
A. はい、XMLは要素の順序を保持します。上から順に記述された通りの順序が維持されます。
Q6. 同じ名前の要素が別の階層にあってもいい?
A. はい、問題ありません。
<data>
<item>外側のitem</item>
<group>
<item>内側のitem</item>
</group>
</data>
XPathやプログラムで処理する際は、階層を意識して取得します。
まとめ
XMLの繰り返し要素の書き方についてまとめます。
基本的な書き方:
- 同じ要素名を複数回記述する
- 親要素で全体をまとめる
- 親要素は複数形、子要素は単数形が推奨
繰り返しのパターン:
- 単純な値の繰り返し
- 複数の子要素を持つ繰り返し
- 属性を含む繰り返し
- 入れ子になった繰り返し
プログラム処理:
- ほとんどの言語でXMLパーサーが利用可能
- 要素の取得とループ処理で繰り返しを扱う
- XPathで柔軟な検索が可能
ベストプラクティス:
- 意味のある要素名を使う
- 一貫性のある構造を保つ
- 深すぎる入れ子を避ける
- 属性と要素を適切に使い分ける
XMLの繰り返しは、同じ要素を複数回書くというシンプルな方法ですが、それゆえに柔軟で強力です。この記事で紹介した方法を使えば、複雑なデータ構造もきれいに表現できますよ。
この記事が、あなたのXML活用の役に立てば嬉しいです。良いXMLライフを!

コメント