XMLの繰り返し要素の書き方を完全解説!基本から実践まで

プログラミング・IT

「XMLで同じ要素を繰り返し書きたいけど、どうすればいいの?」
「商品リストやユーザーリストをXMLで表現する方法が分からない…」

XMLでデータを扱っていると、リストや一覧のように「同じ構造を繰り返す」場面が必ずありますよね。でも、XMLには「繰り返し」を表す特別な構文はありません。

この記事では、XMLで繰り返し構造を表現する方法について、基本から実践的な使い方まで詳しく解説していきます。プログラミング言語での処理方法も紹介するので、実務でもすぐに活用できますよ。

スポンサーリンク
  1. XMLの繰り返しとは?
    1. 繰り返しの基本的な考え方
    2. プログラミング言語の配列・リストとの対応
  2. 基本的な繰り返しの書き方
    1. パターン1:単純な値の繰り返し
    2. パターン2:複数の子要素を持つ繰り返し
    3. パターン3:属性を使った繰り返し
  3. 実践的な繰り返しの例
    1. 例1:商品カタログ
    2. 例2:ブログ記事のリスト
    3. 例3:住所録
    4. 例4:レストランのメニュー
  4. ネストした繰り返し(入れ子構造)
    1. 基本的な入れ子構造
    2. より複雑な入れ子構造
  5. プログラミング言語での処理方法
    1. JavaScript(DOMParser)
    2. Python(xml.etree.ElementTree)
    3. PHP(SimpleXML)
    4. Java(DOM)
  6. XPathでの繰り返し要素の取得
    1. 基本的なXPath式
    2. JavaScript with XPath
  7. XSLTでの繰り返し処理
    1. 基本的なXSLT繰り返し
  8. 繰り返しの書き方:ベストプラクティス
    1. 1. 適切な要素名を使う
    2. 2. 親要素で複数形、子要素で単数形
    3. 3. 深すぎる入れ子を避ける
    4. 4. 属性と要素の使い分け
    5. 5. 一貫性のある構造
  9. よくある間違いと対処法
    1. 間違い1:親要素なしで繰り返す
    2. 間違い2:タグの閉じ忘れ
    3. 間違い3:不正な文字の使用
    4. 間違い4:エンコーディングの不一致
  10. よくある質問と回答
    1. Q1. XMLで配列のインデックスは使える?
    2. Q2. 空の繰り返しはどう書く?
    3. Q3. 繰り返しの数に制限はある?
    4. Q4. JSONとXML、どちらが繰り返しに適している?
    5. Q5. 繰り返しの中で順序は保証される?
    6. Q6. 同じ名前の要素が別の階層にあってもいい?
  11. まとめ

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 &lt; 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の繰り返し要素の書き方についてまとめます。

基本的な書き方:

  • 同じ要素名を複数回記述する
  • 親要素で全体をまとめる
  • 親要素は複数形、子要素は単数形が推奨

繰り返しのパターン:

  1. 単純な値の繰り返し
  2. 複数の子要素を持つ繰り返し
  3. 属性を含む繰り返し
  4. 入れ子になった繰り返し

プログラム処理:

  • ほとんどの言語でXMLパーサーが利用可能
  • 要素の取得とループ処理で繰り返しを扱う
  • XPathで柔軟な検索が可能

ベストプラクティス:

  • 意味のある要素名を使う
  • 一貫性のある構造を保つ
  • 深すぎる入れ子を避ける
  • 属性と要素を適切に使い分ける

XMLの繰り返しは、同じ要素を複数回書くというシンプルな方法ですが、それゆえに柔軟で強力です。この記事で紹介した方法を使えば、複雑なデータ構造もきれいに表現できますよ。

この記事が、あなたのXML活用の役に立てば嬉しいです。良いXMLライフを!

コメント

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