Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.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
在拆分或grep后保留XML名称空间_Xml_Perl - Fatal编程技术网

在拆分或grep后保留XML名称空间

在拆分或grep后保留XML名称空间,xml,perl,Xml,Perl,我有一个巨大的xml文件(几GB),我可以用xml_split分割它,或者用xml_grep提取相关的子节点。如果我试图读取整个XML,内存就会耗尽 但是,当我试图解析一个被拆分的文件或grep:ed文件时,我无数次地收到错误“yy上的名称空间前缀xx未定义” 有没有办法将名称空间定义从原始文件复制到拆分文件或grep:ed文件?还是我误解了错误 我对XML非常陌生,我发现XML::TWIG很有用。下面是我使用的grep命令: xml_grep --root 'SubInformation' -

我有一个巨大的xml文件(几GB),我可以用xml_split分割它,或者用xml_grep提取相关的子节点。如果我试图读取整个XML,内存就会耗尽

但是,当我试图解析一个被拆分的文件或grep:ed文件时,我无数次地收到错误“yy上的名称空间前缀xx未定义”

有没有办法将名称空间定义从原始文件复制到拆分文件或grep:ed文件?还是我误解了错误

我对XML非常陌生,我发现XML::TWIG很有用。下面是我使用的grep命令:

xml_grep --root 'SubInformation' --cond 'SubInformationName[string()="Blah"]' Infile.xml > Outfile.xml

要处理大型XML文件,还可以使用pull解析器。请参阅。

您使用哪个工具来解析拆分结果(或grep)
xmllint
(来自
libxml2
)抱怨,但
xmlwf
(来自
expat
)没有抱怨。所以我认为任何基于expat的工具都可以使用XML,但不能使用基于libxml2的工具

看起来
xml\u split
xml\u grep
可以声明名称空间。至少这应该是一种选择。我来看看

同时,这里有一种快速、肮脏的方法来对使用
xml\u grep
得到的结果进行后处理:

xml_grep --root 'SubInformation' --cond 'SubInformationName[string()="Blah"]' Infile.xml | perl -MXML::Twig -e'XML::Twig->new( start_tag_handlers => { xml_grep => sub { $_->set_att( "xmlns:m" => "http://m.org") }, SubInformation => sub { $_->flush } })->parse( \*STDIN)' > Outfile.xml
替换
xmlns:m
”http://m.org“
中包含适当的值

让我为
xml\u split
的结果想出一种通用的方法。我是否可以假定名称空间声明不是太复杂(即前缀只声明一次)

编辑:在infle.xml上运行
xml\u split
后,可以将名称空间声明添加到由
xml\u split
生成的文件中,称之为
add\ns infle

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my $root= shift @ARGV;

my( $base, @files)= sort glob( "$root-*.xml");

my %ns= ns_for_file( $base);

foreach my $file (@files)
  { add_ns( $file, %ns); }


sub ns_for_file
  { my( $base)= @_;
    my %ns;
    XML::Twig->new( start_tag_handlers
      # get namespace declarations from the root and bail
      => { 'level(0)' => sub { %ns= ns_for_tag( $_); 
                               $_[0]->finish_now(); 
                             } 
         },
                  )
             ->parsefile( $base);
    return %ns;
  }

# get all namespace declarations from the root element
sub ns_for_tag
  { my( $e)= @_;
    return map { $_ => $e->att( $_) if m{^xmlns:} } $e->att_names;
  }

sub add_ns
  { my( $file, %ns)= @_;
     XML::Twig->new( start_tag_handlers => { 'level(0)' => sub { $_->set_att( %ns); } },
                     twig_handlers => { _all_ => sub { $_->flush; } },
                     keep_spaces => 1,
                   )
              ->parsefile_inplace( $file);

}

我使用libxml2。。。或者实际上是“R”(统计语言)中libxml2的包装器。如果libxml2能够解析分割的文件,那就太好了。顺便说一句,谢谢你的好工具!谢谢,现在测试。当我在原始文件上运行grep xmlns时,我看到了5个不同的xmlns:xx=“abc123”,这就是您仅声明一次前缀的引用吗?这5个元素中的每一个都只在onec中列出。名称空间声明都在根元素上吗?我为
xml\u split
添加了一个解决方案。它唯一的假设是名称空间声明位于原始文档的根上。如果不是这样的话,让我知道,它会更复杂一点(我想会慢得多)