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

如何按link字段语言后缀拆分Google供应商标准XML并保留原有结构

问题描述

我有一份符合Google供应商标准的XML文件,包含波兰语和英语两种语言的商品数据,需要拆分为两个独立的XML文件,且完整保留原文件结构。目前的难点是语言标识仅出现在link字段中,以.pl或.en后缀区分。
优先希望能直接生成两个独立文件,仅生成单文件也可以,我可以更换筛选条件运行第二次得到另一个文件。
我原本想用JS实现类似如下逻辑(伪代码):

file.rss.channel.children.filter(item=>{return item.link.includes(".en")})

我尝试用xmlstarlet实现该需求,但没有成功。

输入文件示例

<rss xmlns:g="http://base.google.com/ns/1.0" xmlns:c="http://base.google.com/cns/1.0" version="2.0"><channel><title><![CDATA[ Brand ]]></title><link><![CDATA[ site.link.pl ]]></link><description><![CDATA[  ]]></description><item><g:id>132430</g:id><link><![CDATA[item.link.pl]]></link><g:canonical_link>item.link.pl</g:canonical_link></item><item><g:id>132431</g:id><link><![CDATA[item.link.en]]></link><g:canonical_link>item.link.en</g:canonical_link></item></channel></rss>

预期输出英文版本示例

<rss xmlns:g="http://base.google.com/ns/1.0" xmlns:c="http://base.google.com/cns/1.0" version="2.0"><channel><title><![CDATA[ Brand ]]></title><link><![CDATA[ site.link.pl ]]></link><description><![CDATA[  ]]></description><item><g:id>132431</g:id><link><![CDATA[item.link.en]]></link><g:canonical_link>item.link.en</g:canonical_link></item></channel></rss>

解决方案

方案1:xmlstarlet命令行实现

直接通过删除不符合条件的item节点即可输出目标文件,原XML的公共节点(title、channel根link、description)会完整保留:

# 生成英文版本文件
xmlstarlet ed -d '//item[not(ends-with(link/text(), ".en"))]' 输入文件名.xml > output_en.xml

# 生成波兰语版本文件
xmlstarlet ed -d '//item[not(ends-with(link/text(), ".pl"))]' 输入文件名.xml > output_pl.xml

如果你使用的是旧版本xmlstarlet(仅支持XPath1.0,无ends-with方法),可以替换为contains写法:

# XPath1.0兼容版,生成英文文件
xmlstarlet ed -d '//item[not(contains(link/text(), ".en"))]' 输入文件名.xml > output_en.xml

方案2:Node.js实现(符合你原本的JS逻辑)

如果你更熟悉JS语法,可以用fast-xml-parser库处理,完美保留CDATA、命名空间等原结构:

  1. 安装依赖
npm install fast-xml-parser
  1. 新建处理脚本split-xml.js
const { readFileSync, writeFileSync } = require('fs');
const { XMLParser, XMLBuilder } = require('fast-xml-parser');

// 解析&生成配置,保留所有原结构
const parser = new XMLParser({
  ignoreAttributes: false,
  cdataPropName: '__cdata',
  preserveOrder: true
});
const builder = new XMLBuilder({
  ignoreAttributes: false,
  cdataPropName: '__cdata',
  preserveOrder: true,
  format: true
});

// 读取原文件
const rawXml = readFileSync('输入文件名.xml', 'utf-8');
const xmlTree = parser.parse(rawXml);
const channelNodes = xmlTree[0]['rss'][0]['channel'];

const commonNodes = [];
const enItems = [];
const plItems = [];

// 拆分公共节点和不同语言的商品项
for (const node of channelNodes) {
  const nodeName = Object.keys(node)[0];
  if (nodeName === 'item') {
    const linkNode = node['item'].find(n => Object.keys(n)[0] === 'link')?.['link']?.[0];
    const linkVal = linkNode.__cdata || linkNode['#text'] || '';
    if (linkVal.endsWith('.en')) enItems.push(node);
    else if (linkVal.endsWith('.pl')) plItems.push(node);
  } else {
    commonNodes.push(node);
  }
}

// 输出英文文件
xmlTree[0]['rss'][0]['channel'] = [...commonNodes, ...enItems];
writeFileSync('output_en.xml', builder.build(xmlTree), 'utf-8');

// 输出波兰语文件
xmlTree[0]['rss'][0]['channel'] = [...commonNodes, ...plItems];
writeFileSync('output_pl.xml', builder.build(xmlTree), 'utf-8');
  1. 运行脚本直接生成两个文件
node split-xml.js

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:15:03