2013-03-29 229 views
1

我有一个包含数千个条目的,就像一个XML文件:提取数据

<gml:featureMember> 
<Feature> 
<featureType>JCSOutput</featureType> 
<property name="gml2_coordsys"></property> 
<gml:PointProperty> 
       <gml:Point> 
        <gml:coordinates>4048313.294966287,5374397.792158723 </gml:coordinates> 
       </gml:Point> 

</gml:PointProperty> 
<property name="BEZEICHNUN">Anton-Bosch-Gasse</property> 
<property name="WL_NUMMER">68</property> 
</Feature> 
</gml:featureMember> 


<gml:featureMember> 
<Feature> 
<featureType>JCSOutput</featureType> 
<property name="gml2_coordsys"></property> 
<gml:PointProperty> 
       <gml:Point> 
        <gml:coordinates>4044355.0231338665,5365146.95116724 </gml:coordinates> 
       </gml:Point> 

</gml:PointProperty> 
<property name="BEZEICHNUN">Anschützgasse</property> 
<property name="WL_NUMMER">67</property> 
</Feature> 
</gml:featureMember> 

脚本要在其中搜索列表(例如安东 - 博世Gasse)给出的名称和复制全段开始<gml:featureMember>到一个新的文件

你会用什么为了这个目的 - AWK,sed的,perl的?

回答

3

使用xml_grep,附带XML::Twig,你可以写

$ xml_grep --root 'gml:featureMember' \ 
--cond 'property[string()="Anton-Bosch-Gasse"]' \ 
to_grep.xml > extract.xml
+0

非常感谢你,我用你的解决方案,它是最容易实现的对我来说:-) –

5

Sed和awk不是解析XML的正确工具。达到的Perl:

#!/usr/bin/perl 
use warnings; 
use strict; 

use XML::LibXML; 

my $search = 'Anton-Bosch-Gasse'; 

# Put your real values here! 
my $file = '1.xml'; 
my $uri = 'http://1.2.3'; 

my $xpc = XML::LibXML::XPathContext->new; 
$xpc->registerNs('gml', $uri); 

my $xml = XML::LibXML->load_xml(location => $file); 
my $r = $xml->find("//property[.='$search']/ancestor::gml:featureMember"); 
print $_->serialize for @$r; 

或者,如果你觉得上面的例子太详细,您可以使用xsh

my $search = 'Anton-Bosch-Gasse' ; 
register-namespace gml http://1.2.3 ; # Insert the real URI. 
open 1.xml ;       # Insert the real path. 
ls //property[.=$search]/ancestor::gml:featureMember ; 
1

这是一个像choroba的解决方案,但使用Mojolicious套件。其模块Mojo::DOM使用css3选择器而不是xpath来遍历XML。

在这里,我首先找到所有gml:featureMember元素,然后提取其中具有匹配后代的第一个。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Mojo::DOM; 
use Mojo::Util qw/slurp spurt/; 

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

# read in from file 
# $dom->parse(slurp 'myfile.xml'); 
# but for the demo ... 
$dom->parse(do{ local $/; <DATA> }); 

my $found = 
    $dom->find('gml\:featureMember') 
     ->first(sub{ 
     $_->find('property[name="BEZEICHNUN"]') 
      ->first(qr/\QAnton-Bosch-Gasse/) 
     }); 

spurt "$found", 'output.xml'; 


__DATA__ 
<gml:featureMember> 
<Feature> 
<featureType>JCSOutput</featureType> 
<property name="gml2_coordsys"></property> 
<gml:PointProperty> 
       <gml:Point> 
        <gml:coordinates>4048313.294966287,5374397.792158723 </gml:coordinates> 
       </gml:Point> 

</gml:PointProperty> 
<property name="BEZEICHNUN">Anton-Bosch-Gasse</property> 
<property name="WL_NUMMER">68</property> 
</Feature> 
</gml:featureMember> 


<gml:featureMember> 
<Feature> 
<featureType>JCSOutput</featureType> 
<property name="gml2_coordsys"></property> 
<gml:PointProperty> 
       <gml:Point> 
        <gml:coordinates>4044355.0231338665,5365146.95116724 </gml:coordinates> 
       </gml:Point> 

</gml:PointProperty> 
<property name="BEZEICHNUN">Anschützgasse</property> 
<property name="WL_NUMMER">67</property> 
</Feature> 
</gml:featureMember> 

对于本例,我从DATA部分获取XML。您可以使用注释的代码从文件中解析。

如果您确定该属性在结构中始终处于两个深度,您也可以更有效一些。

my $found = 
    $dom->find('gml\:featureMember property[name="BEZEICHNUN"]') 
     ->first(qr/\QAnton-Bosch-Gasse/) 
     ->parent 
     ->parent;