【问题标题】:Extract data from xml file从xml文件中提取数据
【发布时间】:2013-03-20 02:22:28
【问题描述】:

我有一个包含数千个条目的 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>

脚本应搜索列表中给出的名称(例如 Anton-Bosch-Gasse)并将以 &lt;gml:featureMember&gt; 开头的整个段落复制到新文件中

你会为此目的使用什么 - awk、sed、perl?

【问题讨论】:

    标签: xml perl sed awk text-processing


    【解决方案1】:

    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 ;
    

    【讨论】:

      【解决方案2】:

      使用xml_grepXML::Twig自带,可以写

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

      【讨论】:

      • 非常感谢,我使用了你的解决方案,对我来说这是最容易实现的:-)
      【解决方案3】:

      这是一个类似于 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;
      

      【讨论】:

        猜你喜欢
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-02
        • 1970-01-01
        • 1970-01-01
        • 2011-01-14
        • 1970-01-01
        相关资源
        最近更新 更多