You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历XML并将国家-地区-城市数据存入MySQL表?

从XML层级数据到MySQL存储的完整实现指南

我来帮你梳理从国家-地区-城市层级XML数据到MySQL存储的完整流程,从数据库表结构设计到PHP代码落地都给你讲清楚:

一、先搞定MySQL表结构设计

针对你这种明确的三级层级数据,推荐设计三个关联表,数据结构清晰且易于维护:

1. 国家表 (countries)

用来存储国家编码和名称,比如GR对应希腊:

CREATE TABLE countries (
    country_id INT AUTO_INCREMENT PRIMARY KEY,
    country_code VARCHAR(2) NOT NULL UNIQUE, -- 唯一的国家编码
    country_name VARCHAR(100) NOT NULL
);

2. 地区表 (regions)

关联对应的国家,存储地区的编码和名称:

CREATE TABLE regions (
    region_id INT AUTO_INCREMENT PRIMARY KEY,
    country_id INT NOT NULL,
    region_code VARCHAR(50) NOT NULL, -- 地区编码,比如GR-AT
    region_name VARCHAR(100) NOT NULL,
    FOREIGN KEY (country_id) REFERENCES countries(country_id) ON DELETE CASCADE
);

3. 城市表 (cities)

关联对应的地区,存储城市的编码和名称:

CREATE TABLE cities (
    city_id INT AUTO_INCREMENT PRIMARY KEY,
    region_id INT NOT NULL,
    city_code VARCHAR(50) NOT NULL, -- 城市编码,比如GR-ATH
    city_name VARCHAR(100) NOT NULL,
    FOREIGN KEY (region_id) REFERENCES regions(region_id) ON DELETE CASCADE
);

如果觉得分表麻烦,也可以用单表自关联的方式,但三级结构下分表更易后续查询和维护。


二、PHP完整遍历与存储代码

假设你已经能获取到每个国家的XML文件,下面基于SimpleXML完成读取、遍历、入库的完整逻辑,用PDO操作数据库更安全:

1. 封装数据库连接

先写个复用的数据库连接函数,避免重复代码:

function getDbConnection() {
    $host = 'localhost';
    $dbname = '你的数据库名';
    $username = '你的用户名';
    $password = '你的密码';
    
    try {
        $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $pdo;
    } catch(PDOException $e) {
        die("数据库连接失败: " . $e->getMessage());
    }
}

2. 遍历XML并插入数据

先假设你的XML结构是这样的(结合你提到的地区/城市示例简化):

示例XML结构:

<country code="GR" name="希腊">
    <regions>
        <region code="GR-AT" name="阿提卡">
            <cities>
                <city code="GR-ATH" name="雅典"/>
                <city code="GR-PIR" name="比雷埃夫斯"/>
            </cities>
        </region>
    </regions>
</country>

对应的PHP处理代码:

// 获取数据库连接
$pdo = getDbConnection();

// 假设你已经有所有国家XML文件的路径数组,比如$countryXmlFiles = ['gr.xml', 'cn.xml', ...];
foreach ($countryXmlFiles as $xmlPath) {
    // 加载XML文件,失败则跳过当前文件
    $xml = simplexml_load_file($xmlPath);
    if (!$xml) {
        echo "加载XML文件失败: $xmlPath<br>";
        continue;
    }

    // 1. 插入国家数据(先检查是否已存在,避免重复)
    $countryCode = (string)$xml['code'];
    $countryName = (string)$xml['name'];
    
    $stmt = $pdo->prepare("SELECT country_id FROM countries WHERE country_code = ?");
    $stmt->execute([$countryCode]);
    $countryId = $stmt->fetchColumn();
    
    if (!$countryId) {
        $stmt = $pdo->prepare("INSERT INTO countries (country_code, country_name) VALUES (?, ?)");
        $stmt->execute([$countryCode, $countryName]);
        $countryId = $pdo->lastInsertId();
    }

    // 2. 遍历所有地区
    foreach ($xml->regions->region as $regionNode) {
        $regionCode = (string)$regionNode['code'];
        $regionName = (string)$regionNode['name'];
        
        // 检查地区是否已存在
        $stmt = $pdo->prepare("SELECT region_id FROM regions WHERE country_id = ? AND region_code = ?");
        $stmt->execute([$countryId, $regionCode]);
        $regionId = $stmt->fetchColumn();
        
        if (!$regionId) {
            $stmt = $pdo->prepare("INSERT INTO regions (country_id, region_code, region_name) VALUES (?, ?, ?)");
            $stmt->execute([$countryId, $regionCode, $regionName]);
            $regionId = $pdo->lastInsertId();
        }

        // 3. 遍历当前地区下的所有城市
        // 先判断是否存在城市节点,避免空遍历报错
        if (isset($regionNode->cities->city)) {
            foreach ($regionNode->cities->city as $cityNode) {
                $cityCode = (string)$cityNode['code'];
                $cityName = (string)$cityNode['name'];
                
                // 检查城市是否已存在
                $stmt = $pdo->prepare("SELECT city_id FROM cities WHERE region_id = ? AND city_code = ?");
                $stmt->execute([$regionId, $cityCode]);
                $cityId = $stmt->fetchColumn();
                
                if (!$cityId) {
                    $stmt = $pdo->prepare("INSERT INTO cities (region_id, city_code, city_name) VALUES (?, ?, ?)");
                    $stmt->execute([$regionId, $cityCode, $cityName]);
                }
            }
        }
    }
    
    echo "成功处理国家: $countryName ($countryCode)<br>";
}

三、几个关键注意点

  • 数据去重:每次插入前先查询是否已存在对应数据,避免重复入库(尤其是如果XML文件可能被重复处理的情况)。
  • 字符编码:确保数据库连接用utf8mb4,和XML文件编码一致,避免中文或特殊字符乱码。
  • 异常处理:可以在代码中添加更多try-catch块,捕获XML解析或数据库操作的异常,方便排查问题。比如在遍历XML的循环外包裹try-catch:
    try {
        // 遍历XML的逻辑
    } catch (Exception $e) {
        echo "处理$xmlPath时出错: " . $e->getMessage() . "<br>";
        continue;
    }
    
  • 批量插入优化:如果数据量很大,建议用批量插入提升效率。比如收集多个城市数据后,用INSERT INTO cities (...) VALUES (...), (...), (...)的格式一次性插入。
  • XML容错:如果有些地区没有城市节点,一定要用isset()判断,避免报错。

内容的提问来源于stack exchange,提问作者Abdul Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:28:12