0

我正在使用 Perl 和 XML::LibXML,我必须处理的 XML 如下所示:

<PARAM NAME = "A"><VALUE>1</VALUE>
<PARAM NAME = "B"><VALUE>3</VALUE>
<PARAM NAME = "C"><VALUE>43</VALUE>
<PARAM NAME = "A"><VALUE>6</VALUE>
<PARAM NAME = "B"><VALUE>3</VALUE>
<PARAM NAME = "C"><VALUE>13</VALUE>
.
.
.

我需要的输出基本上是:

A    B    C
1    3    43
6    3    13

我已将文字节点名称放入这样的数组中:

my @attributes = (
    './PARAM[@NAME = "A"]/VALUE',
    './PARAM[@NAME = "B"]/VALUE',
    .
    .
);

然后将 findnodes() 和 findvalue() 与这些 xpath 文字一起用作 foreach 循环中的参数,错误地尝试获取“一组”值以写入记录。自然,findnodes() 是错误的,因为它在每次循环中获取满足条件的所有节点(正如它应该做的那样),而 findvalues() 是错误的,因为它实际上做同样的事情,只是连接所有类似的-命名节点值。

由于这个文件的结构是这样的,我看不出有办法捕获“A到C”节点/值,写一条记录,然后重复……至少在不检查每个节点是否是“最后一个”的情况下不会一个'('C')。看来我基本上需要将它作为一个普通的旧文本文件来处理。

4

3 回答 3

0

Your data isn't actually valid XML as there's no closing tag for each PARAM. Therefore you'll either need to clean up the data before running through a XML Parser, or use a regular expression.

The following uses a regex to parse any number of fields and values:

use strict;
use warnings;

my %seen_header;
my @headers;
my @data = {};

while (<DATA>) {
    if (m{<PARAM NAME = "(.*?)"><VALUE>(.*?)</VALUE>}i) {
        my $name = $1;
        my $val = $2;

        push @headers, $name if ! $seen_header{$name}++;
        push @data, {} if exists $data[-1]{$name};
        $data[-1]{$name} = $val;

    } else {
        warn "Unrecognized format at line $.: $_"
    }
}

print "@headers\n";
print join(' ', map {$_ // ''} @{$_}{@headers}), "\n" for (@data);

__DATA__
<PARAM NAME = "A"><VALUE>1</VALUE>
<PARAM NAME = "B"><VALUE>3</VALUE>
<PARAM NAME = "C"><VALUE>43</VALUE>
<PARAM NAME = "A"><VALUE>6</VALUE>
<PARAM NAME = "B"><VALUE>3</VALUE>
<PARAM NAME = "C"><VALUE>13</VALUE>

Outputs:

A B C
1 3 43
6 3 13

Could also adapt this code for using an XML Parser, but I'll leave that up to you if it's what you want.

于 2014-05-16T03:42:11.590 回答
0

您没有提供您使用的语言,但它似乎是 perl。基本上,获取所有<VALUE/>元素(分别是它们的文本节点)然后循环遍历它们,每次读取三个值。

在一种有点失败的伪代码中:

@attributes = xpath('//PARAM/VALUE');
for ($i = 0; i < length(@attributes); i += 3)
  push @records (@attributes[$i], @attributes[$i + 1], @attributes[$i + 2])

结果,您应该得到一个数组数组(当然,您也可以返回一个哈希数组)。如果您只想要输出,请使用上面的模式并适当调用printf而不是push.

于 2014-04-22T21:21:19.613 回答
0

这是我采用的一种方法:

foreach my $parameter ( $raid_group->findnodes('PARAM')) {
    my $name  = $parameter->findvalue('@NAME);
    my $value = $parameter->findvalue('VALUE');
    if ($name eq $first_name_in_set ){
        [do stuff]
    }
}

这是我认为使用螺丝刀进行凿子的情况——方便但仅此而已。

于 2014-04-23T14:12:25.950 回答