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

解析PLC L5X文件,提取CDATA节点中的目标字符串(如'Sec')

提取L5X文件CDATA节点中的字符串(Perl + XML::LibXML)

我帮你搞定这个需求!你已经在用XML::LibXML处理L5X的Timer标签了,要从<![CDATA['Sec']]>里提取纯字符串Sec其实非常直接,只需要在现有代码里加几行逻辑就行。

步骤说明

  1. 定位CDATA节点:从你的L5X片段来看,目标CDATA位于StructureMember[@Name="SP"]下的StructureMember[@Name="Unit"]节点内的DataValueMember[@Name="DATA"]里。
  2. 获取CDATA内容:XML::LibXML的findvalue方法会自动处理CDATA标记,直接返回里面的文本内容,不需要额外解析<![CDATA[...]]>。
  3. 清理字符串:CDATA里的内容带有单引号,用正则去掉前后的单引号就能得到纯Sec字符串。

修改后的完整代码

foreach (@L5Xfiles) { 
    my $input="RSL_Export/"."$_"; 
    open(my $data, '<', $input) or die "Can't open < $input: $!"; 
    my $parser = XML::LibXML->new(); 
    my $doc = $parser->parse_file($input); 
    foreach my $tag ($doc ->findnodes('//Tag')) { 
        my $atag = $tag->getAttribute('DataType'); 
        if (defined($atag) && $atag =~ /Timer_Tag/) { 
            my $name=$tag->getAttribute('Name'); 
            my $out=$tag->findvalue('Data/Structure/StructureMember[@Name="SP"]/DataValueMember[@Name="Out"]/@Value'); 
            my $secmin=$tag->findvalue('Data/Structure/DataValueMember[@Name="UnitsSelect"]/@Value'); 
            my $min=$tag->findvalue('Data/Structure/StructureMember[@Name="SP"]/StructureMember[@Name="EU"]/DataValueMember[@Name="Min"]/@Value'); 
            my $max=$tag->findvalue('Data/Structure/StructureMember[@Name="SP"]/StructureMember[@Name="EU"]/DataValueMember[@Name="Max"]/@Value'); 
            
            # 新增:提取CDATA中的单位字符串并清理
            my $unit_str = $tag->findvalue('Data/Structure/StructureMember[@Name="SP"]/StructureMember[@Name="Unit"]/DataValueMember[@Name="DATA"]');
            $unit_str =~ s/^'|'$//g; # 精准去掉前后的单引号
            
            my $name_L0 = $name; 
            $name =~ s/_/\_/g; 
            $secmin =~ s/0/Sec/g; 
            $secmin =~ s/1/Min/g; 
            $timers{'TimerConfig'}{'TimerConfig'}{$name}=$out . " " . $secmin; 
            my $RSLTAG = $name_L0; 
            $TimerTestTags{$RSLTAG} ={
                RSLTAG=>$RSLTAG,
                L0=>$name_L0,
                L1=>'',
                L2=>'',
                L0_Type=>$atag,
                L1_Type=>'',
                L2_Type=>'',
                SP=>$out,
                Unit=>$secmin,
                Unit_From_CDATA=>$unit_str, # 新增字段存储提取的纯字符串
                Min=>$min,
                Max=>$max
            }; 
        } 
    } 
}

关键细节解释

  • findvalue方法会自动忽略CDATA标记,直接返回'Sec'这个文本内容。
  • 正则s/^'|'$//g只删除字符串开头和结尾的单引号,避免误删内容中间可能出现的单引号(虽然这个场景里不太可能,但更严谨)。
  • 新增的Unit_From_CDATA字段用来单独存储从CDATA提取的纯字符串,你可以根据需求调整字段名,或者替换现有的Unit字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:27:47