Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用重复的同级节点组导航XML_Xml_Xpath_Xml Parsing_Xml Libxml - Fatal编程技术网

如何使用重复的同级节点组导航XML

如何使用重复的同级节点组导航XML,xml,xpath,xml-parsing,xml-libxml,Xml,Xpath,Xml Parsing,Xml Libxml,我使用的是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>

我使用的是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>
.
.
.
my @attributes = (
    './PARAM[@NAME = "A"]/VALUE',
    './PARAM[@NAME = "B"]/VALUE',
    .
    .
);
我已将文字节点名称放入如下数组:

<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>
.
.
.
my @attributes = (
    './PARAM[@NAME = "A"]/VALUE',
    './PARAM[@NAME = "B"]/VALUE',
    .
    .
);
然后使用findnodes()和findvalue()以及这些xpath文本作为foreach循环中的参数,错误地试图获取一组值以写入记录。 当然,findnodes()是错误的,因为它在循环的每次传递中都会获得满足条件的所有节点(正如它应该做的那样),而findvalues()是错误的,因为它实际上做了相同的事情,只是将所有类似的命名节点值串联在一起


由于这个文件的结构是这样的,我认为没有办法捕获“A到C”节点/值,写一条记录,然后重复…至少在不检查每个节点以确定它是否是“最后一个”(“C”)的情况下是这样的。基本上,我需要将其作为一个纯文本文件进行处理。

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

在某种程度上是一种伪代码:

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

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

以下是我采用的一种有效方法:

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]
    }
}

这是一个用螺丝刀凿凿子的例子,我认为这是权宜之计,但仅此而已。

您的数据实际上不是有效的XML,因为每个参数都没有结束标记。因此,您需要在运行XML解析器之前清理数据,或者使用正则表达式

下面使用正则表达式来解析任意数量的字段和值:

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>

也可以将此代码修改为使用XML解析器,但如果您需要,我将由您决定。

谢谢。源文件不在我的控制之下,因此我需要假设属性节点的“集合”可以更改——事实上,我刚刚发现它们可以更改。我所做的是: