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

如何用Perl的XML::LibXML替换XML中特定父节点的子节点值?

解决XML::LibXML替换指定节点子节点值的问题

Hey there! Let's fix that issue you're having with XML::LibXML. The core problem here is that your current XPath queries are globally searching for <number> and <busNumber> across the entire document, so they always pick up the first matching nodes (from the Consignee business entry) instead of targeting the ones under the Shipper's <business> node.

问题根源

When you run $doc->findnodes('//shipment//business//number//text()'), the // syntax starts searching from the root of the document every time—ignoring the fact that you already found the Shipper's <business> node. That's why the wrong nodes get modified.

修正后的代码

Here's the adjusted script that targets only the Shipper's <number> and <busNumber> values:

use strict;
use warnings;
use XML::LibXML;

my $parser = XML::LibXML->new;
my $doc = $parser->parse_file("Test.xml");
my $root = $doc->getDocumentElement();

## ERROR KEY ENTRY_MISSING
if ( my $valdExpHBill = $doc->findnodes('//shipment//flag[string()="true"]') ) {
    print "valid flag is true\n";
    
    ## ID_MISSING
    # Directly locate all <business> nodes where Type is "Shipper"
    my @shipperBusinessNodes = $doc->findnodes('//shipment//business[Type[string()="Shipper"]]');
    
    foreach my $businessNode (@shipperBusinessNodes) {
        print "Shipper business exist under this shipment\n";
        
        # Use relative XPath to find <number> within the current <business> node
        if (my ($numberText) = $businessNode->findnodes('./number/text()')) {
            $numberText->setData(' ');
        }
        
        # Do the same for <busNumber>
        if (my ($busNumberText) = $businessNode->findnodes('./busNumber/text()')) {
            $busNumberText->setData(' ');
        }
    }
    
    # Save the modified XML
    my $EDE5 = $doc->toFile("ID_MISSING.xml", 1);
}

关键改动说明

  1. Target the right nodes upfront:
    The XPath //shipment//business[Type[string()="Shipper"]] directly finds all <business> nodes that have a <Type> child with the value "Shipper"—no need to find the Type node first and then backtrack.

  2. Use relative XPath for child nodes:
    Instead of using // to search globally, we use ./number/text() which searches only within the current <business> node (the one we already identified as Shipper). This ensures we modify exactly the nodes we want.

  3. Handle multiple Shipper nodes (just in case):
    By looping over @shipperBusinessNodes, the script will work even if there are multiple Shipper entries in your XML—each one's <number> and <busNumber> will be cleared.

验证结果

With this code, your output XML will match your expected result:

<shipment>
  <flag>true</flag>
  <business>
    <Type>Consignee</Type>
    <number>G0213</number>
    <busNumber>3006</busNumber>
  </business>
  <business>
    <Type>Shipper</Type>
    <number> </number>
    <busNumber> </busNumber>
  </business>
</shipment>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:29:36