XMLをテーブル表示する方法|見やすい表形式でデータを表示しよう

プログラミング・IT

「XMLファイルのデータを、Excelのような表形式で見やすく表示したい」

XMLファイルには構造化されたデータが含まれていますが、そのままでは読みにくく、一覧性に欠けます。特に大量のデータを扱う場合、テーブル(表)形式で表示できると格段に見やすくなりますよね。

この記事では、XMLデータをテーブル形式で表示する様々な方法を、実践的なコード例とともに詳しく解説します。HTMLとJavaScript、XSLT、CSSを使った方法まで、初心者の方でも理解できるよう丁寧に説明していきますね。

スポンサーリンク

XMLのテーブル表示とは?基本を理解しよう

XMLデータの構造

XMLは階層構造でデータを保存する形式です。

XMLデータの例

<?xml version="1.0" encoding="UTF-8"?>
<employees>
    <employee>
        <id>001</id>
        <name>田中太郎</name>
        <department>営業部</department>
        <salary>350000</salary>
    </employee>
    <employee>
        <id>002</id>
        <name>鈴木花子</name>
        <department>開発部</department>
        <salary>420000</salary>
    </employee>
</employees>

このようなXMLデータを、以下のようなテーブル形式で表示することが目標です。

ID名前部署給与
001田中太郎営業部350000
002鈴木花子開発部420000

テーブル表示が役立つ場面

XMLのテーブル表示は、以下のような場面で特に役立ちます。

データ分析
複数のレコードを比較しやすくなります。

レポート作成
見栄えの良い表形式でデータを提示できます。

データの確認作業
XMLファイルの内容を素早く確認できます。

Webページでの表示
データベースから出力したXMLをWebサイトで見やすく表示できます。

テーブル表示の3つの主な方法

XMLをテーブル表示する方法は、大きく分けて3つあります。

方法1:HTML + JavaScript
XMLデータを読み込んで、JavaScriptで動的にHTMLテーブルを生成する方法です。

メリット

  • 柔軟なカスタマイズが可能
  • フィルタリングやソート機能を追加しやすい
  • 最も多機能

方法2:XSLT変換
XSLTを使ってXMLを直接HTMLテーブルに変換する方法です。

メリット

  • サーバーサイドでもクライアントサイドでも使える
  • XMLの標準技術
  • JavaScriptを使わない

方法3:CSS スタイリング
XMLに直接CSSを適用してテーブル風に表示する方法です。

メリット

  • 最もシンプル
  • 軽量で高速
  • 基本的な表示には十分

それぞれの方法を詳しく見ていきましょう。

HTML + JavaScriptでテーブル表示

基本的な実装方法

JavaScriptを使ってXMLを解析し、HTMLテーブルを生成します。

XMLファイル(employees.xml)

<?xml version="1.0" encoding="UTF-8"?>
<employees>
    <employee>
        <id>001</id>
        <name>田中太郎</name>
        <department>営業部</department>
        <salary>350000</salary>
    </employee>
    <employee>
        <id>002</id>
        <name>鈴木花子</name>
        <department>開発部</department>
        <salary>420000</salary>
    </employee>
    <employee>
        <id>003</id>
        <name>佐藤一郎</name>
        <department>人事部</department>
        <salary>380000</salary>
    </employee>
</employees>

HTMLファイル(index.html)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XML テーブル表示</title>
    <style>
        body {
            font-family: "メイリオ", sans-serif;
            max-width: 1000px;
            margin: 20px auto;
            padding: 20px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        th {
            background-color: #4CAF50;
            color: white;
            padding: 12px;
            text-align: left;
            font-weight: bold;
        }
        td {
            padding: 10px;
            border-bottom: 1px solid #ddd;
        }
        tr:hover {
            background-color: #f5f5f5;
        }
        tr:nth-child(even) {
            background-color: #f9f9f9;
        }
    </style>
</head>
<body>
    <h1>従業員一覧</h1>
    <div id="tableContainer"></div>

    <script>
        // XMLファイルを読み込む
        fetch('employees.xml')
            .then(response => response.text())
            .then(data => {
                // XMLをパース(解析)
                const parser = new DOMParser();
                const xmlDoc = parser.parseFromString(data, 'text/xml');

                // テーブルを生成
                createTable(xmlDoc);
            })
            .catch(error => {
                console.error('エラー:', error);
                document.getElementById('tableContainer').innerHTML = 
                    '<p style="color: red;">XMLファイルの読み込みに失敗しました。</p>';
            });

        function createTable(xmlDoc) {
            // employee要素を全て取得
            const employees = xmlDoc.getElementsByTagName('employee');

            // テーブルのHTML生成開始
            let tableHTML = '<table>';
            tableHTML += '<thead><tr>';
            tableHTML += '<th>ID</th>';
            tableHTML += '<th>名前</th>';
            tableHTML += '<th>部署</th>';
            tableHTML += '<th>給与</th>';
            tableHTML += '</tr></thead>';
            tableHTML += '<tbody>';

            // 各従業員のデータを行として追加
            for (let i = 0; i < employees.length; i++) {
                const employee = employees[i];

                const id = employee.getElementsByTagName('id')[0].textContent;
                const name = employee.getElementsByTagName('name')[0].textContent;
                const department = employee.getElementsByTagName('department')[0].textContent;
                const salary = employee.getElementsByTagName('salary')[0].textContent;

                tableHTML += '<tr>';
                tableHTML += `<td>${id}</td>`;
                tableHTML += `<td>${name}</td>`;
                tableHTML += `<td>${department}</td>`;
                tableHTML += `<td>${Number(salary).toLocaleString()}円</td>`;
                tableHTML += '</tr>';
            }

            tableHTML += '</tbody></table>';

            // 生成したテーブルを表示
            document.getElementById('tableContainer').innerHTML = tableHTML;
        }
    </script>
</body>
</html>

より実践的な実装(検索・ソート機能付き)

検索やソート機能を追加した、より実用的な例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XML テーブル表示(高機能版)</title>
    <style>
        body {
            font-family: "メイリオ", sans-serif;
            max-width: 1200px;
            margin: 20px auto;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .controls {
            background: white;
            padding: 15px;
            margin-bottom: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .search-box {
            width: 100%;
            padding: 10px;
            font-size: 16px;
            border: 2px solid #ddd;
            border-radius: 4px;
            box-sizing: border-box;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            background: white;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        th {
            background-color: #4CAF50;
            color: white;
            padding: 12px;
            text-align: left;
            font-weight: bold;
            cursor: pointer;
            position: relative;
        }
        th:hover {
            background-color: #45a049;
        }
        th::after {
            content: ' ⇅';
            font-size: 12px;
            opacity: 0.5;
        }
        td {
            padding: 10px;
            border-bottom: 1px solid #ddd;
        }
        tr:hover {
            background-color: #f5f5f5;
        }
        tr:nth-child(even) {
            background-color: #f9f9f9;
        }
        .no-results {
            text-align: center;
            padding: 20px;
            color: #666;
        }
    </style>
</head>
<body>
    <h1>従業員一覧(検索・ソート機能付き)</h1>

    <div class="controls">
        <input type="text" id="searchBox" class="search-box" 
               placeholder="名前や部署で検索...">
    </div>

    <div id="tableContainer"></div>

    <script>
        let employeesData = [];
        let sortOrder = { column: '', asc: true };

        // XMLファイルを読み込む
        fetch('employees.xml')
            .then(response => response.text())
            .then(data => {
                const parser = new DOMParser();
                const xmlDoc = parser.parseFromString(data, 'text/xml');
                loadEmployees(xmlDoc);
                displayTable();
            })
            .catch(error => {
                console.error('エラー:', error);
                document.getElementById('tableContainer').innerHTML = 
                    '<p style="color: red;">XMLファイルの読み込みに失敗しました。</p>';
            });

        // XMLからデータを読み込む
        function loadEmployees(xmlDoc) {
            const employees = xmlDoc.getElementsByTagName('employee');

            for (let i = 0; i < employees.length; i++) {
                const employee = employees[i];

                employeesData.push({
                    id: employee.getElementsByTagName('id')[0].textContent,
                    name: employee.getElementsByTagName('name')[0].textContent,
                    department: employee.getElementsByTagName('department')[0].textContent,
                    salary: parseInt(employee.getElementsByTagName('salary')[0].textContent)
                });
            }
        }

        // テーブルを表示
        function displayTable(filteredData = employeesData) {
            if (filteredData.length === 0) {
                document.getElementById('tableContainer').innerHTML = 
                    '<div class="no-results">該当するデータが見つかりませんでした。</div>';
                return;
            }

            let tableHTML = '<table>';
            tableHTML += '<thead><tr>';
            tableHTML += '<th onclick="sortTable(\'id\')">ID</th>';
            tableHTML += '<th onclick="sortTable(\'name\')">名前</th>';
            tableHTML += '<th onclick="sortTable(\'department\')">部署</th>';
            tableHTML += '<th onclick="sortTable(\'salary\')">給与</th>';
            tableHTML += '</tr></thead>';
            tableHTML += '<tbody>';

            filteredData.forEach(emp => {
                tableHTML += '<tr>';
                tableHTML += `<td>${emp.id}</td>`;
                tableHTML += `<td>${emp.name}</td>`;
                tableHTML += `<td>${emp.department}</td>`;
                tableHTML += `<td>${emp.salary.toLocaleString()}円</td>`;
                tableHTML += '</tr>';
            });

            tableHTML += '</tbody></table>';
            document.getElementById('tableContainer').innerHTML = tableHTML;
        }

        // ソート機能
        function sortTable(column) {
            if (sortOrder.column === column) {
                sortOrder.asc = !sortOrder.asc;
            } else {
                sortOrder.column = column;
                sortOrder.asc = true;
            }

            const sorted = [...employeesData].sort((a, b) => {
                let valA = a[column];
                let valB = b[column];

                if (typeof valA === 'string') {
                    valA = valA.toLowerCase();
                    valB = valB.toLowerCase();
                }

                if (sortOrder.asc) {
                    return valA > valB ? 1 : -1;
                } else {
                    return valA < valB ? 1 : -1;
                }
            });

            displayTable(sorted);
        }

        // 検索機能
        document.getElementById('searchBox').addEventListener('input', function(e) {
            const searchTerm = e.target.value.toLowerCase();

            if (searchTerm === '') {
                displayTable();
                return;
            }

            const filtered = employeesData.filter(emp => {
                return emp.name.toLowerCase().includes(searchTerm) ||
                       emp.department.toLowerCase().includes(searchTerm);
            });

            displayTable(filtered);
        });
    </script>
</body>
</html>

ローカルサーバーでの動作確認

XMLファイルを読み込む際、CORS(Cross-Origin)の制限により、ファイルを直接開くと動作しないことがあります。

Pythonでローカルサーバーを起動

# XMLとHTMLファイルがあるフォルダで実行
python -m http.server 8000

その後、ブラウザで http://localhost:8000/index.html にアクセスします。

XSLTでテーブル表示

XSLT変換の基本

XSLTを使うと、XMLを直接HTMLテーブルに変換できます。

XMLファイル(products.xml)

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="table.xsl"?>
<products>
    <product>
        <id>P001</id>
        <name>ノートパソコン</name>
        <price>89800</price>
        <stock>15</stock>
    </product>
    <product>
        <id>P002</id>
        <name>マウス</name>
        <price>1980</price>
        <stock>50</stock>
    </product>
    <product>
        <id>P003</id>
        <name>キーボード</name>
        <price>4500</price>
        <stock>30</stock>
    </product>
</products>

XSLTファイル(table.xsl)

<?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>
            <head>
                <meta charset="UTF-8"/>
                <title>商品一覧</title>
                <style>
                    body {
                        font-family: "メイリオ", sans-serif;
                        max-width: 1000px;
                        margin: 20px auto;
                        padding: 20px;
                    }
                    h1 {
                        color: #333;
                        border-bottom: 3px solid #4CAF50;
                        padding-bottom: 10px;
                    }
                    table {
                        width: 100%;
                        border-collapse: collapse;
                        box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                        margin-top: 20px;
                    }
                    th {
                        background-color: #4CAF50;
                        color: white;
                        padding: 12px;
                        text-align: left;
                        font-weight: bold;
                    }
                    td {
                        padding: 10px;
                        border-bottom: 1px solid #ddd;
                    }
                    tr:hover {
                        background-color: #f5f5f5;
                    }
                    tr:nth-child(even) {
                        background-color: #f9f9f9;
                    }
                    .price {
                        text-align: right;
                        color: #e74c3c;
                        font-weight: bold;
                    }
                    .stock {
                        text-align: center;
                    }
                    .low-stock {
                        color: #ff9800;
                        font-weight: bold;
                    }
                </style>
            </head>
            <body>
                <h1>商品一覧</h1>
                <table>
                    <thead>
                        <tr>
                            <th>商品ID</th>
                            <th>商品名</th>
                            <th>価格</th>
                            <th>在庫数</th>
                        </tr>
                    </thead>
                    <tbody>
                        <xsl:apply-templates select="products/product"/>
                    </tbody>
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="product">
        <tr>
            <td><xsl:value-of select="id"/></td>
            <td><xsl:value-of select="name"/></td>
            <td class="price">
                <xsl:value-of select="format-number(price, '#,###')"/>円
            </td>
            <td class="stock">
                <xsl:choose>
                    <xsl:when test="stock &lt; 20">
                        <span class="low-stock">
                            <xsl:value-of select="stock"/>個 (少)
                        </span>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="stock"/>個
                    </xsl:otherwise>
                </xsl:choose>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

このXMLファイルをブラウザで開くと、自動的にXSLT変換が実行され、HTMLテーブルとして表示されます。

条件分岐を使った高度な表示

XSLTでは、データの値に応じて表示を変えることができます。

条件に応じた色分けの例

<xsl:template match="product">
    <tr>
        <xsl:choose>
            <xsl:when test="stock = 0">
                <xsl:attribute name="style">background-color: #ffebee;</xsl:attribute>
            </xsl:when>
            <xsl:when test="stock &lt; 10">
                <xsl:attribute name="style">background-color: #fff3e0;</xsl:attribute>
            </xsl:when>
        </xsl:choose>

        <td><xsl:value-of select="id"/></td>
        <td><xsl:value-of select="name"/></td>
        <td class="price">
            <xsl:value-of select="format-number(price, '#,###')"/>円
        </td>
        <td class="stock">
            <xsl:choose>
                <xsl:when test="stock = 0">
                    <span style="color: red; font-weight: bold;">在庫切れ</span>
                </xsl:when>
                <xsl:when test="stock &lt; 10">
                    <span style="color: orange; font-weight: bold;">
                        <xsl:value-of select="stock"/>個 (残りわずか)
                    </span>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="stock"/>個
                </xsl:otherwise>
            </xsl:choose>
        </td>
    </tr>
</xsl:template>

CSSだけでテーブル風表示

display: tableを使った方法

JavaScriptやXSLTを使わず、CSSだけでテーブル風の表示を実現できます。

XMLファイル(books.xml)

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="table.css"?>
<books>
    <book>
        <title>XMLプログラミング入門</title>
        <author>山田太郎</author>
        <price>2800</price>
        <publisher>技術出版社</publisher>
    </book>
    <book>
        <title>Web開発の基礎</title>
        <author>鈴木花子</author>
        <price>3200</price>
        <publisher>開発社</publisher>
    </book>
    <book>
        <title>データベース設計</title>
        <author>佐藤一郎</author>
        <price>3500</price>
        <publisher>DB出版</publisher>
    </book>
</books>

CSSファイル(table.css)

@charset "UTF-8";

books {
    display: table;
    width: 100%;
    border-collapse: collapse;
    font-family: "メイリオ", sans-serif;
    margin: 20px;
}

books::before {
    content: "";
    display: table-row;
    font-weight: bold;
    background-color: #4CAF50;
    color: white;
}

book {
    display: table-row;
    border-bottom: 1px solid #ddd;
}

book:nth-child(even) {
    background-color: #f9f9f9;
}

book:hover {
    background-color: #f5f5f5;
}

title, author, price, publisher {
    display: table-cell;
    padding: 12px;
    border: 1px solid #ddd;
}

/* 疑似要素でヘッダーを作成 */
book:first-child title::before {
    content: "書籍名";
    display: block;
    font-weight: bold;
    background-color: #4CAF50;
    color: white;
    padding: 12px;
    margin: -12px -12px 12px -12px;
}

book:first-child author::before {
    content: "著者";
    display: block;
    font-weight: bold;
    background-color: #4CAF50;
    color: white;
    padding: 12px;
    margin: -12px -12px 12px -12px;
}

book:first-child price::before {
    content: "価格";
    display: block;
    font-weight: bold;
    background-color: #4CAF50;
    color: white;
    padding: 12px;
    margin: -12px -12px 12px -12px;
}

book:first-child publisher::before {
    content: "出版社";
    display: block;
    font-weight: bold;
    background-color: #4CAF50;
    color: white;
    padding: 12px;
    margin: -12px -12px 12px -12px;
}

price::after {
    content: "円";
}

この方法は、XMLファイルをブラウザで直接開くだけで、テーブル風の表示になります。

実践的な応用例

複雑な構造のXMLをテーブル化

ネストした(入れ子になった)XMLデータをテーブル表示する例です。

XMLファイル(orders.xml)

<?xml version="1.0" encoding="UTF-8"?>
<orders>
    <order>
        <orderID>ORD001</orderID>
        <date>2024-11-10</date>
        <customer>
            <name>田中太郎</name>
            <email>tanaka@example.com</email>
        </customer>
        <items>
            <item>
                <product>ノートPC</product>
                <quantity>1</quantity>
                <price>89800</price>
            </item>
            <item>
                <product>マウス</product>
                <quantity>2</quantity>
                <price>1980</price>
            </item>
        </items>
        <total>93760</total>
    </order>
</orders>

JavaScriptでの処理例

function createOrderTable(xmlDoc) {
    const orders = xmlDoc.getElementsByTagName('order');

    let tableHTML = '<table>';
    tableHTML += '<thead><tr>';
    tableHTML += '<th>注文ID</th>';
    tableHTML += '<th>日付</th>';
    tableHTML += '<th>顧客名</th>';
    tableHTML += '<th>メール</th>';
    tableHTML += '<th>商品</th>';
    tableHTML += '<th>合計金額</th>';
    tableHTML += '</tr></thead>';
    tableHTML += '<tbody>';

    for (let i = 0; i < orders.length; i++) {
        const order = orders[i];

        const orderID = order.getElementsByTagName('orderID')[0].textContent;
        const date = order.getElementsByTagName('date')[0].textContent;
        const customerName = order.getElementsByTagName('customer')[0]
            .getElementsByTagName('name')[0].textContent;
        const email = order.getElementsByTagName('customer')[0]
            .getElementsByTagName('email')[0].textContent;
        const total = order.getElementsByTagName('total')[0].textContent;

        // 商品一覧を作成
        const items = order.getElementsByTagName('item');
        let itemsList = '<ul style="margin: 0; padding-left: 20px;">';
        for (let j = 0; j < items.length; j++) {
            const product = items[j].getElementsByTagName('product')[0].textContent;
            const quantity = items[j].getElementsByTagName('quantity')[0].textContent;
            itemsList += `<li>${product} × ${quantity}</li>`;
        }
        itemsList += '</ul>';

        tableHTML += '<tr>';
        tableHTML += `<td>${orderID}</td>`;
        tableHTML += `<td>${date}</td>`;
        tableHTML += `<td>${customerName}</td>`;
        tableHTML += `<td>${email}</td>`;
        tableHTML += `<td>${itemsList}</td>`;
        tableHTML += `<td style="text-align: right; font-weight: bold;">
                        ${Number(total).toLocaleString()}円</td>`;
        tableHTML += '</tr>';
    }

    tableHTML += '</tbody></table>';

    return tableHTML;
}

ExcelライクなUIの実装

スプレッドシートのような見た目と操作性を実現する例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Excel風テーブル</title>
    <style>
        body {
            font-family: "メイリオ", sans-serif;
            margin: 20px;
        }
        .excel-table {
            border: 1px solid #d0d7de;
            border-collapse: collapse;
            width: 100%;
        }
        .excel-table th {
            background: linear-gradient(180deg, #f6f8fa 0%, #e9ebef 100%);
            border: 1px solid #d0d7de;
            padding: 8px 12px;
            font-weight: 600;
            text-align: left;
            position: sticky;
            top: 0;
        }
        .excel-table td {
            border: 1px solid #d0d7de;
            padding: 6px 12px;
            background: white;
        }
        .excel-table tr:hover {
            background-color: #f6f8fa;
        }
        .excel-table td:focus {
            outline: 2px solid #0969da;
            outline-offset: -2px;
        }
        .row-number {
            background: linear-gradient(180deg, #f6f8fa 0%, #e9ebef 100%);
            color: #57606a;
            font-weight: 600;
            text-align: center;
            width: 50px;
        }
        .summary {
            margin-top: 20px;
            padding: 15px;
            background: #f6f8fa;
            border-radius: 6px;
            border: 1px solid #d0d7de;
        }
    </style>
</head>
<body>
    <h1>データ分析ダッシュボード</h1>
    <div id="tableContainer"></div>
    <div id="summary" class="summary"></div>

    <script>
        // XMLを読み込んで処理
        fetch('employees.xml')
            .then(response => response.text())
            .then(data => {
                const parser = new DOMParser();
                const xmlDoc = parser.parseFromString(data, 'text/xml');
                displayExcelTable(xmlDoc);
                calculateSummary(xmlDoc);
            });

        function displayExcelTable(xmlDoc) {
            const employees = xmlDoc.getElementsByTagName('employee');

            let html = '<table class="excel-table">';
            html += '<thead><tr>';
            html += '<th class="row-number">#</th>';
            html += '<th>ID</th>';
            html += '<th>名前</th>';
            html += '<th>部署</th>';
            html += '<th>給与</th>';
            html += '</tr></thead>';
            html += '<tbody>';

            for (let i = 0; i < employees.length; i++) {
                const emp = employees[i];
                html += '<tr>';
                html += `<td class="row-number">${i + 1}</td>`;
                html += `<td>${emp.getElementsByTagName('id')[0].textContent}</td>`;
                html += `<td>${emp.getElementsByTagName('name')[0].textContent}</td>`;
                html += `<td>${emp.getElementsByTagName('department')[0].textContent}</td>`;
                html += `<td>${Number(emp.getElementsByTagName('salary')[0].textContent).toLocaleString()}円</td>`;
                html += '</tr>';
            }

            html += '</tbody></table>';
            document.getElementById('tableContainer').innerHTML = html;
        }

        function calculateSummary(xmlDoc) {
            const employees = xmlDoc.getElementsByTagName('employee');
            let totalSalary = 0;
            let count = employees.length;

            for (let i = 0; i < employees.length; i++) {
                const salary = parseInt(employees[i].getElementsByTagName('salary')[0].textContent);
                totalSalary += salary;
            }

            const avgSalary = Math.round(totalSalary / count);

            let html = '<h3>集計データ</h3>';
            html += `<p><strong>従業員数:</strong> ${count}名</p>`;
            html += `<p><strong>給与総額:</strong> ${totalSalary.toLocaleString()}円</p>`;
            html += `<p><strong>平均給与:</strong> ${avgSalary.toLocaleString()}円</p>`;

            document.getElementById('summary').innerHTML = html;
        }
    </script>
</body>
</html>

よくある問題と解決方法

問題1:XMLファイルが読み込めない

原因
CORSの制限により、ローカルファイルを直接読み込めません。

解決方法
ローカルサーバーを起動して、http://localhost経由でアクセスします。

# Pythonがインストールされている場合
python -m http.server 8000

# Node.jsの場合
npx http-server

問題2:日本語が文字化けする

原因
文字エンコーディングの設定が間違っています。

解決方法
すべてのファイルをUTF-8で保存し、XMLヘッダーを確認します。

<?xml version="1.0" encoding="UTF-8"?>

HTMLファイルにも文字コードを指定:

<meta charset="UTF-8">

問題3:スタイルが適用されない

原因
CSSやXSLTファイルのパスが間違っているか、ファイルが見つかりません。

解決方法

  1. ファイルパスを確認(相対パス・絶対パス)
  2. ブラウザの開発者ツール(F12)でネットワークエラーを確認
  3. ファイル名の大文字小文字を確認

問題4:テーブルが正しく表示されない

原因
XMLの構造が想定と異なるか、要素名が間違っています。

解決方法

// デバッグ用のコードを追加
console.log(xmlDoc);
console.log(xmlDoc.getElementsByTagName('employee').length);

// 要素の内容を確認
const firstEmployee = xmlDoc.getElementsByTagName('employee')[0];
console.log(firstEmployee.getElementsByTagName('name')[0].textContent);

問題5:大量のデータで動作が遅い

原因
数千件以上のデータを一度に表示しようとしています。

解決方法
ページネーション(ページ分割)を実装します。

let currentPage = 1;
const itemsPerPage = 50;

function displayPage(data, page) {
    const start = (page - 1) * itemsPerPage;
    const end = start + itemsPerPage;
    const pageData = data.slice(start, end);

    // pageDataだけを表示
    displayTable(pageData);

    // ページネーション情報を表示
    displayPagination(data.length, page);
}

function displayPagination(totalItems, currentPage) {
    const totalPages = Math.ceil(totalItems / itemsPerPage);

    let html = '<div class="pagination">';
    for (let i = 1; i <= totalPages; i++) {
        if (i === currentPage) {
            html += `<span class="current">${i}</span>`;
        } else {
            html += `<a href="#" onclick="displayPage(employeesData, ${i}); return false;">${i}</a>`;
        }
    }
    html += '</div>';

    document.getElementById('pagination').innerHTML = html;
}

よくある質問と回答

Q1. ExcelからXMLに変換したデータをテーブル表示できますか?

はい、できます。ExcelでXML形式で保存したデータも、同じ方法でテーブル表示できます。

手順

  1. Excelで「ファイル」→「名前を付けて保存」
  2. 「XMLデータ」形式を選択
  3. この記事で紹介した方法でテーブル表示

ただし、Excel独自の形式が含まれる場合は、データの構造を確認して調整が必要です。

Q2. モバイル端末でも見やすく表示できますか?

はい、レスポンシブデザインを適用することで対応できます。

CSSの追加例

@media (max-width: 768px) {
    table {
        font-size: 12px;
    }
    th, td {
        padding: 6px;
    }
    /* 横スクロールを許可 */
    .table-container {
        overflow-x: auto;
    }
}

Q3. 特定の列だけを表示したい場合は?

JavaScriptやXSLTで、必要な列だけを選択して表示できます。

JavaScript例

// idとnameだけを表示
function createSimpleTable(xmlDoc) {
    // ヘッダーとデータ生成で必要な列だけを処理
    tableHTML += '<th>ID</th><th>名前</th>';
    // ...
}

Q4. テーブルをExcelにエクスポートできますか?

JavaScriptライブラリを使えば、テーブルデータをExcel形式でダウンロードできます。

SheetJSを使った例

<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
<script>
function exportToExcel() {
    const table = document.querySelector('table');
    const workbook = XLSX.utils.table_to_book(table);
    XLSX.writeFile(workbook, 'data.xlsx');
}
</script>
<button onclick="exportToExcel()">Excelにエクスポート</button>

Q5. リアルタイムでXMLデータを更新したい場合は?

定期的にXMLファイルを再読み込みする方法があります。

function refreshTable() {
    fetch('employees.xml?' + new Date().getTime())
        .then(response => response.text())
        .then(data => {
            const xmlDoc = new DOMParser().parseFromString(data, 'text/xml');
            displayTable(xmlDoc);
        });
}

// 5秒ごとに更新
setInterval(refreshTable, 5000);

まとめ

XMLデータをテーブル表示する方法を、3つのアプローチで解説しました。

この記事の重要なポイントをまとめます。

3つの表示方法

HTML + JavaScript

  • 最も柔軟で多機能
  • 検索、ソート、フィルタリングが実装可能
  • 動的な更新に対応しやすい
  • CORSに注意が必要

XSLT変換

  • XML標準の技術
  • サーバーサイドでもクライアントサイドでも使用可能
  • 条件分岐など複雑な変換が可能
  • JavaScriptなしで動作

CSS スタイリング

  • 最もシンプル
  • 軽量で高速
  • 基本的な表示には十分
  • カスタマイズに限界あり

選び方のポイント

シンプルな表示だけなら
CSSスタイリングが最適です。

検索やソート機能が必要なら
HTML + JavaScriptを選びましょう。

標準技術で実装したいなら
XSLTが適しています。

実装時の注意点

  • 文字エンコーディングはUTF-8に統一
  • ローカルサーバーを使用してCORS問題を回避
  • 大量データはページネーションで対応
  • ブラウザの開発者ツールでデバッグ

XMLデータをテーブル表示できるようになると、データの可視化や分析作業が格段に効率的になります。この記事で紹介したコード例を参考に、自分のプロジェクトに合った方法を選んでくださいね。

まずは基本的な例から試してみて、徐々に機能を追加していくのがおすすめです。実際に手を動かしながら学んでいきましょう。

コメント

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