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

基于Perl的XML::LibXML DOM方法按属性值拆分XML文件

用Perl的XML::LibXML DOM方法拆分XML到多个文件(按属性值)

我来帮你实现这个需求——基于元素的string属性值,把原XML拆分到两个独立文件。下面是完整的Perl代码实现,用XML::LibXML的DOM操作来处理,逻辑清晰且鲁棒性强:

完整代码示例

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

# 1. 解析源XML文件(可替换为你的XML路径或直接传入XML字符串)
my $parser = XML::LibXML->new();
my $source_doc = $parser->parse_file('source.xml'); # 也可用parse_string($xml_content)直接解析字符串
my $root = $source_doc->documentElement();

# 2. 定义要拆分的属性值与对应输出文件的映射
my %targets = (
    'ops' => 'ops.xml',
    'spt' => 'spt.xml'
);

# 3. 遍历每个目标属性值,生成对应拆分文件
foreach my $attr_value (keys %targets) {
    # 创建新的DOM文档实例
    my $new_doc = XML::LibXML::Document->new('1.0', 'UTF-8');
    
    # 复制根节点到新文档(先不复制子节点,后续手动筛选处理)
    my $new_root = $new_doc->importNode($root, 0);
    $new_doc->setDocumentElement($new_root);
    
    # 遍历源根节点的所有子节点,筛选并复制到新文档
    foreach my $child_node ($root->childNodes()) {
        # 跳过空白文本节点,避免生成冗余空行
        next if $child_node->nodeType == XML_TEXT_NODE && $child_node->data =~ /^\s*$/;
        
        if ($child_node->nodeName eq 'PrimaryConnection') {
            # 处理PrimaryConnection:保留Port公共节点,筛选对应属性的Address
            my $new_pc = $new_doc->importNode($child_node, 0);
            $new_root->appendChild($new_pc);
            
            foreach my $pc_child ($child_node->childNodes()) {
                if ($pc_child->nodeName eq 'Port') {
                    # 复制公共Port节点
                    my $imported_port = $new_doc->importNode($pc_child, 1);
                    $new_pc->appendChild($imported_port);
                } elsif ($pc_child->nodeName eq 'Address') {
                    # 只保留匹配当前属性值的Address
                    if ($pc_child->getAttribute('string') eq $attr_value) {
                        my $imported_addr = $new_doc->importNode($pc_child, 1);
                        $new_pc->appendChild($imported_addr);
                    }
                }
            }
        } elsif ($child_node->nodeName eq 'SecondaryConnection') {
            # 处理SecondaryConnection:只保留匹配当前属性值的节点
            if ($child_node->getAttribute('string') eq $attr_value) {
                my $imported_sc = $new_doc->importNode($child_node, 1);
                $new_root->appendChild($imported_sc);
            }
        } else {
            # 复制其他公共节点(比如Name这类无属性的通用节点)
            my $imported_child = $new_doc->importNode($child_node, 1);
            $new_root->appendChild($imported_child);
        }
    }
    
    # 保存拆分后的XML文件,第二个参数1表示格式化输出(带缩进)
    $new_doc->toFile($targets{$attr_value}, 1);
}

print "XML拆分完成!\n";

关键细节说明

  • 节点归属处理:必须使用importNode方法将源文档的节点导入到新文档,否则会出现DOM节点归属错误。参数1表示递归复制子节点,0表示仅复制当前节点。
  • 空白节点过滤:跳过XML中的空白文本节点,确保生成的XML文件结构整洁,无多余空行。
  • 扩展性:如果后续需要拆分更多属性值,只需在%targets哈希中添加新的键值对即可。

示例输出效果

针对你提供的XML片段,拆分后的ops.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<LocalJMS>
  <Name>ZLAT</Name>
  <PrimaryConnection>
    <Port>77777</Port>
    <Address string="ops">ops.zla</Address>
  </PrimaryConnection>
  <SecondaryConnection string="ops">
    <Address>abc.zla</Address>
  </SecondaryConnection>
</LocalJMS>

spt.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<LocalJMS>
  <Name>ZLAT</Name>
  <PrimaryConnection>
    <Port>77777</Port>
    <Address string="spt">spt.zla</Address>
  </PrimaryConnection>
</LocalJMS>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:17:26