PHP如何查找XML中匹配CSV ID的节点并按指定次数复制插入
解决方案
你当前使用的SimpleXML扩展原生不支持便捷的节点复制插入操作,我们可以结合PHP内置的DOM扩展完成需求(SimpleXML节点可直接和DOM节点互相转换,无需额外重写读取逻辑),修改后可用代码如下:
<?php $sourceFile = 'doc.xml'; $targetFile = 'doc_new.xml'; $csvFile = 'data.csv'; // 先复制原文件避免操作失误损坏原始数据 if (!copy($sourceFile, $targetFile)) { exit("failed to copy source file"); } // 读取CSV数据,跳过表头行 $csvData = []; $fh = fopen($csvFile, "r"); // 如果你的CSV没有表头,删除下面这行即可 fgetcsv($fh, 0, ";"); while (($row = fgetcsv($fh, 0, ";")) !== FALSE) { // 只保留ID、Number字段都有效的行 if (!empty($row[0]) && isset($row[1]) && is_numeric($row[1])) { $csvData[] = [ 'id' => trim($row[0]), 'copy_count' => (int)$row[1] ]; } } fclose($fh); if (!file_exists($sourceFile)) { exit("source xml file not exists"); } $xml = simplexml_load_file($sourceFile); // 初始化DOM对象用于克隆插入节点 $dom = dom_import_simplexml($xml)->ownerDocument; foreach ($csvData as $item) { $searchId = $item['id']; $copyTimes = $item['copy_count']; // 复制次数小于1无需处理 if ($copyTimes <= 0) { continue; } // 查找匹配节点 $matchedNodes = $xml->xpath("/node/media/image[contains(@id,'$searchId')]"); foreach ($matchedNodes as $simplexmlNode) { // 转成DOM节点方便操作 $domNode = dom_import_simplexml($simplexmlNode); $parentNode = $domNode->parentNode; // 原有节点已经算1个,只需额外复制copyTimes-1次 for ($i = 0; $i < $copyTimes - 1; $i++) { // 深度克隆节点,保留所有子节点和属性 $cloneNode = $domNode->cloneNode(true); // 插入到原节点后方,需要插到父节点末尾可替换为$parentNode->appendChild($cloneNode) $parentNode->insertBefore($cloneNode, $domNode->nextSibling); } } } // 保存修改后的文件 $xml->asXml($targetFile); ?>
注意事项
- 如果你需要复制后的节点ID唯一,可以在克隆节点之后新增修改ID的逻辑,示例:
$cloneNode->setAttribute('id', $searchId . '_' . $i); - 代码自动过滤了Number值小于1的行,不需要复制的行可以直接填0跳过处理
内容的提问来源于stack exchange,提问作者Števo Kelbel
相关产品推荐
相关产品推荐

