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

通过PHP按SKU属性合并多个同结构XML文件

问题

我有3个结构相同的XML文件,需要通过PHP按productsku属性合并,规则如下:

  • 相同productsku的<product>元素合并属性:保留已有属性,补充缺失的属性
  • 目标文件中不存在的<product>元素直接添加

现有代码仅对数字类型SKU有效,且只能处理2个文件,无法适配我的非数字SKU和3个文件的需求,请求提供可行的PHP代码片段。

示例文件

1.xml

<data>
<product productsku="ABC1" price="550000" pricesale="" hn="1"></product>
<product productsku="ABC2" price="" pricesale="" hn="0"></product>
</data>

2.xml

<data>
<product productsku="ABC2" price="550000" pricesale="" dn="2"></product>
<product productsku="ABC3" price="" pricesale="" dn="0"></product>
</data>

3.xml

<data>
<product productsku="ABC3" price="550000" pricesale="" gn="3"></product>
<product productsku="ABC4" price="" pricesale="" gn="0"></product>
</data>

期望合并结果

<data><product productsku="ABC1" price="550000" pricesale="" hn="1"></product>
<product productsku="ABC2" price="550000" pricesale="" dn="2" hn="0"></product>
<product productsku="ABC3" price="550000" pricesale="" dn="0" gn="3"></product>
<product productsku="ABC4" price="" pricesale="" gn="0"></product>
</data>

现有尝试代码

<?php 
$xml1 = file_get_contents('1.xml');
$xml2 = file_get_contents('2.xml');
$targetDom = new DOMDocument();
$targetDom->loadXml($xml1);
$targetXpath = new DOMXpath($targetDom);

$addDom = new DOMDocument();
$addDom->loadXml($xml2);
$addXpath = new DOMXpath($addDom);

// merge attributes of product elements depending on productsku
foreach ($targetXpath->evaluate('//product[@productsku]') as $product) {
  $productsku = $product->getAttribute('productsku');
  foreach ($addXpath->evaluate('//product[@productsku='.$productsku.']/@*') as $attribute) {
    if (!$product->hasAttribute($attribute->name)) {
      $product->setAttribute($attribute->name, $attribute->value);
    }
  }
}

// copy products elements that are not in target dom
foreach ($addXpath->evaluate('//product[@productsku]') as $product) {
  $productsku = $product->getAttribute('productsku');
  if ($targetXpath->evaluate('count(//product[@productsku='.$productsku.'])') == 0) {
    $targetDom->documentElement->appendChild(
      $targetDom->importNode($product)
    );
  }
}
echo $targetDom->saveXml();

解决方案

现有代码的核心问题有两个:

  1. XPath查询中,非数字类型的SKU没有用引号包裹,导致XPath语法错误
  2. 仅硬编码处理2个文件,无法扩展到3个及以上文件

以下是修正后的代码,支持任意数量的XML文件和非数字SKU:

<?php
// 定义需要合并的所有XML文件路径
$xmlFiles = ['1.xml', '2.xml', '3.xml'];

// 初始化目标DOM,以第一个文件为基础
$targetDom = new DOMDocument();
$targetDom->load($xmlFiles[0]);
$targetXpath = new DOMXPath($targetDom);

// 循环处理剩余的XML文件
for ($i = 1; $i < count($xmlFiles); $i++) {
    $currentFile = $xmlFiles[$i];
    $addDom = new DOMDocument();
    $addDom->load($currentFile);
    $addXpath = new DOMXPath($addDom);
    
    // 1. 合并已有SKU的属性
    foreach ($addXpath->evaluate('//product[@productsku]') as $sourceProduct) {
        $sku = $sourceProduct->getAttribute('productsku');
        // 使用XPath变量绑定,避免字符串拼接的语法问题,同时更安全
        $targetProducts = $targetXpath->evaluate('//product[@productsku = $sku]', null, ['sku' => $sku]);
        
        if ($targetProducts->length > 0) {
            $targetProduct = $targetProducts->item(0);
            // 遍历源产品的所有属性,补充目标产品缺失的属性
            foreach ($sourceProduct->attributes as $attr) {
                if (!$targetProduct->hasAttribute($attr->name)) {
                    $targetProduct->setAttribute($attr->name, $attr->value);
                }
            }
        } else {
            // 2. 目标中不存在的SKU,直接导入节点
            $importedNode = $targetDom->importNode($sourceProduct, true);
            $targetDom->documentElement->appendChild($importedNode);
        }
    }
}

// 输出合并后的XML(可替换为保存到文件)
$targetDom->formatOutput = true; // 可选:格式化输出,便于阅读
echo $targetDom->saveXML();
// 若要保存到文件,使用:$targetDom->save('merged.xml');

代码说明

  • 批量处理文件:通过数组定义所有待合并的XML文件,循环处理,支持任意数量的文件
  • 安全的XPath查询:使用XPath变量绑定$sku,避免非数字SKU因未加引号导致的语法错误,同时防止注入风险
  • 合并逻辑优化:遍历源文件的产品,先检查目标中是否存在相同SKU,存在则补充属性,不存在则直接导入,逻辑更清晰
  • 可选格式化:开启formatOutput可让输出的XML更易读,按需使用

内容的提问来源于stack exchange,提问作者Phan Vũ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:40:24