读取以特定字符串开头的所有xml标记的内容

时间:2019-01-28 16:25:14

标签: regex xml perl xml-parsing

我有一个xml结构,我希望编写一个perl脚本来读取以特定字符串开头的所有标签的内容。

示例:

<tag-0>
    <tag-1>This is<tag-2>some example</tag2>text</tag-1>
    <tag-3>This is some <ice-8> more </ice-8>text</tag-3>
    <tag-4>This 
        <tag-5>is 
            <tag-6>even more</tag-6>
        </tag-5> 
        <tag-7> text</tag-7>
    </tag-4>
</tag-0>

该脚本的目的是查找以<tag-[num]>开头的所有包含嵌套<tag-[num]>的节点。我对perl不熟悉,那么我将如何读取“动态”标签的内容,并检查更多的动态嵌套标签?

在上面的示例中,我想获取tag-0,tag-1,tag-4和tag-5,然后可以进一步操纵它们的内容。

2 个答案:

答案 0 :(得分:2)

XML::LibXML是我最常用的XML模块-还有很多其他模块,但是这个模块几乎可以满足我的所有需求,但有时会比其他模块更加冗长。下面显示了四个所需的节点:

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

my $dom = XML::LibXML->load_xml(string => <<'EOT');
<tag-0>
    <tag-1>This is<tag-2>some example</tag-2>text</tag-1>
    <tag-3>This is some <ice-8> more </ice-8>text</tag-3>
    <tag-4>This 
        <tag-5>is 
            <tag-6>even more</tag-6>
        </tag-5> 
        <tag-7> text</tag-7>
    </tag-4>
</tag-0>
EOT

my $expr = "*[substring(name(), 1, 4) = 'tag-']";
for my $node ( $dom->findnodes("//$expr") ) {
    my @children = $node->findnodes("./$expr");
    if (@children) {
        print $node->nodeName,"\n";
    }
}

请注意,您的问题描述有点不清楚:“包含嵌套的<tag-[num]>意味着仅考虑直接后代,还是应该返回<tag-0>A<x>B<tag-1>C</tag-1>D</x>E</tag-0> tag-0

如果是这样,则可以将第二个findnodes表达式更改为".//$expr"

答案 1 :(得分:1)

使用Mojo::DOM

use strict;
use warnings;
use Mojo::DOM;

my $dom = Mojo::DOM->new->xml(1)->parse($xml);

my @tags_with_subtags = $dom->find('*')->grep(sub {
  $_->tag =~ m/\Atag-[0-9]+\z/ and $_->find('*')->grep(sub {
    $_->tag =~ m/\Atag-[0-9]+\z/
  })->size
})->each;

每个结果都是一个Mojo :: DOM对象,您可以进一步搜索或操作。不幸的是,CSS(据我所知)并不适合查找动态标签名称,因此您必须自己做一点;如果它是动态属性,那将非常容易。