如何在Unix环境下为XML文件的指定节点添加关联字段
需求描述
处理包含多个<creditnote>节点的XML文件,每个<creditnote>下有<items>节点,<items>包含一个或多个<item>子节点。需要为每个<item>节点添加所属<creditnote>中的<order_id>字段内容,以便ETL工具分步骤加载时能关联数据。
原始XML示例
<creditnote> <creditmemo_increment_id>000000003</creditmemo_increment_id> <creditmemo_entity_id>3</creditmemo_entity_id> <order_increment_id>000000378</order_increment_id> <order_id>371</order_id> <total_refunded>2908.9300</total_refunded> <tax_refunded>543.9500</tax_refunded> <shipping_refunded>0.0000</shipping_refunded> <shipping_tax_refunded>0.0000</shipping_tax_refunded> <creditmemo_created_at/> <creditmemo_updated_at/> <payment> <method>stripe_payments</method> <method_title>Pay online</method_title> <amount_refunded>2908.9300</amount_refunded> <base_amount_refunded>2908.9300</base_amount_refunded> </payment> <items> <item> <sku>31363</sku> <name>iPhone 16 Pro 256GB Natural Titanium</name> <qty_ordered>2.0000</qty_ordered> <qty_refunded>2.0000</qty_refunded> <price>1169.9900</price> <row_total>2339.9800</row_total> <tax_amount>538.2000</tax_amount> <discount_amount>0.0000</discount_amount> <tax_refunded>538.2000</tax_refunded> <qty_refunded>2.0000</qty_refunded> </item> <item> <sku>3Broadband Unlimited 5G Gold Outdoor</sku> <name>3Broadband Unlimited 5G Gold Outdoor [5G_outdoor]</name> <qty_ordered>1.0000</qty_ordered> <qty_refunded>1.0000</qty_refunded> <price>25.0000</price> <row_total>25.0000</row_total> <tax_amount>5.7500</tax_amount> <discount_amount>0.0000</discount_amount> <tax_refunded>5.7500</tax_refunded> <qty_refunded>1.0000</qty_refunded> </item> </items> </creditnote> <creditnote> <creditmemo_increment_id>000000001</creditmemo_increment_id> <creditmemo_entity_id>1</creditmemo_entity_id> <order_increment_id>000000155</order_increment_id> <order_id>153</order_id> <total_refunded>13.5300</total_refunded> <items> <item> <sku>48009</sku> <name>DL My Charger Lightning Disp</name> <qty_ordered>1.0000</qty_ordered> <qty_refunded>1.0000</qty_refunded> <price>11.0000</price> <row_total>11.0000</row_total> <tax_amount>2.5300</tax_amount> <discount_amount>0.0000</discount_amount> <tax_refunded>2.5300</tax_refunded> <qty_refunded>1.0000</qty_refunded> </item> </items> </creditnote>
目标XML示例
<creditnote> <creditmemo_increment_id>000000003</creditmemo_increment_id> <creditmemo_entity_id>3</creditmemo_entity_id> <order_increment_id>000000378</order_increment_id> <order_id>371</order_id> <total_refunded>2908.9300</total_refunded> <tax_refunded>543.9500</tax_refunded> <shipping_refunded>0.0000</shipping_refunded> <shipping_tax_refunded>0.0000</shipping_tax_refunded> <creditmemo_created_at/> <creditmemo_updated_at/> <payment> <method>stripe_payments</method> <method_title>Pay online</method_title> <amount_refunded>2908.9300</amount_refunded> <base_amount_refunded>2908.9300</base_amount_refunded> </payment> <items> <item> <order_id>371</order_id> <sku>31363</sku> <name>iPhone 16 Pro 256GB Natural Titanium</name> <qty_ordered>2.0000</qty_ordered> <qty_refunded>2.0000</qty_refunded> <price>1169.9900</price> <row_total>2339.9800</row_total> <tax_amount>538.2000</tax_amount> <discount_amount>0.0000</discount_amount> <tax_refunded>538.2000</tax_refunded> <qty_refunded>2.0000</qty_refunded> </item> <item> <order_id>371</order_id> <sku>3Broadband Unlimited 5G Gold Outdoor</sku> <name>3Broadband Unlimited 5G Gold Outdoor [5G_outdoor]</name> <qty_ordered>1.0000</qty_ordered> <qty_refunded>1.0000</qty_refunded> <price>25.0000</price> <row_total>25.0000</row_total> <tax_amount>5.7500</tax_amount> <discount_amount>0.0000</discount_amount> <tax_refunded>5.7500</tax_refunded> <qty_refunded>1.0000</qty_refunded> </item> </items> </creditnote> <creditnote> <creditmemo_increment_id>000000001</creditmemo_increment_id> <creditmemo_entity_id>1</creditmemo_entity_id> <order_increment_id>000000155</order_increment_id> <order_id>153</order_id> <total_refunded>13.5300</total_refunded> <items> <item> <order_id>153</order_id> <sku>48009</sku> <name>DL My Charger Lightning Disp</name> <qty_ordered>1.0000</qty_ordered> <qty_refunded>1.0000</qty_refunded> <price>11.0000</price> <row_total>11.0000</row_total> <tax_amount>2.5300</tax_amount> <discount_amount>0.0000</discount_amount> <tax_refunded>2.5300</tax_refunded> <qty_refunded>1.0000</qty_refunded> </item> </items> </creditnote>
Unix环境下的实现方法
方法一:使用XSLT(推荐,XML标准处理方式)
Unix环境下常用xsltproc工具执行XSLT转换,几乎所有发行版都预装或可通过包管理器安装(如Debian/Ubuntu用apt install xsltproc,CentOS/RHEL用yum install libxslt)。
步骤1:创建XSLT转换文件(命名为add_order_id.xsl)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 复制所有节点和属性的默认规则 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配每个item节点,插入所属creditnote的order_id --> <xsl:template match="item"> <xsl:copy> <order_id> <xsl:value-of select="../../order_id"/> </order_id> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
步骤2:执行转换命令
假设原始XML文件名为input.xml,执行以下命令生成处理后的output.xml:
xsltproc add_order_id.xsl input.xml > output.xml
方法二:使用awk(应急方案,仅适用于格式规范的简单XML)
如果环境中没有XSLT工具,可尝试用awk处理,但依赖XML的格式化格式(节点无跨换行、嵌套结构简单):
awk ' /<creditnote>/ { in_creditnote=1; order_id="" } in_creditnote && /<order_id>/ { sub(/<order_id>/, "", $0) sub(/<\/order_id>/, "", $0) order_id=$0 } /<item>/ { print "<item>"; print " <order_id>" order_id "</order_id>"; next } { print } ' input.xml > output.xml
注意:若
<order_id>或<item>节点跨多行,此方法会出错。
内容的提问来源于stack exchange,提问作者Sergio Jimenez
相关产品推荐
相关产品推荐

