我正在处理.xml文件,我需要一个perl脚本。我会尽力解释。我的输入格式如下:
<p t="opener">
<w id="23">
<o>Hi</o>
</w>
<w id="24">
<o>world</o>
</w>
</p>
也就是说,每个单词(Hi,world)由一个标签(<o></o>
)分隔,另外,它有一个相关的数字,它不是从1开始。这个编号显示为一个值标签<w></w>
内的属性“id”。最后,有一个顶级(<p></p>
)表示不同的段落。
我需要的输出必须具有以下格式:
<p t="opener">
<w id="1">
<o>Hi</o>
</w>
<w id="2">
<o>world</o>
</w>
</p>
即,与输入相同的格式,但从1开始获得相关编号
我想解决方案必须涉及自动增量运算符(++),但事情变得更加困难,因为我需要应用从1开始的相关编号,只要段落具有属性“opener”(喜欢输入)
换句话说,我需要的是一个从1开始打印所需编号的条件,以防段落是“开场白”。我的建议是:
use warnings;
use strict;
$/ = undef
my $numbering = 0;
my $autonumbering = $numbering++;
my $filename = shift;
open F, $filename or die "Usa: $0 FILENAME\n";
while (<F>) {
if (/<p t=\"opener\".*?<\/p>/s) {
# If the paragraph is <p t="opener"></p> (the dot (.) stands for every character, including \n)
s/<w id=\".*?\"/<w id=\"$autonumbering\"/ge # replace the value of "id" by the variable $autonumbering
}
}
close F;
我知道,实际上,我并没有告诉Perl仅在所需段落中应用替换。如果条件为真,我只是告诉将替换应用于整个文件,不是吗?
有任何建议可以帮助我应用限制并优化我的提案吗?
答案 0 :(得分:4)
在没有使用专用XML库的情况下,我从未见过处理XML数据的好借口。
此程序使用XML::LibXML
并且似乎按照您的要求执行。
将来请在编译程序之前不要放弃并寻求免费帮助。
use strict;
use warnings;
use XML::LibXML;
my $doc = XML::LibXML->load_xml(location => 'my.xml');
my $id;
for my $w_element ($doc->findnodes('//p[@t="opener"]/w[@id]')) {
$w_element->setAttribute('id', ++$id);
}
print $doc->toString;
<强>输出强>
<?xml version="1.0"?>
<p t="opener">
<w id="1">
<o>Hi</o>
</w>
<w id="2">
<o>world</o>
</w>
</p>