分析器错误:打开和结束标签不匹配:

时间:2012-10-09 09:25:29

标签: perl xml-parsing mod-perl

我在阅读XML文件时遇到问题。如果你看下面的xml,你会看到元素<fl> ?fl>而不是<fl></fl>。我收到错误打开和结束标记不匹配。

如何:

  1. XML文件中存在错误,例如<fl> ?fl>而不是<fl></fl>。如何在读取xml时忽略这样的错误或修复它们而不是用它来解析?
  2. 我只想阅读$_->{desc}->[0]->{en}->[0]而非<de><es><fl>的内容。
  3. 现在我正在阅读XML文件,如:

    package test::test6382_sunseekingeurope;
    use strict;
    use warnings;
    use test;
    use base qw/test/;
    use URI::URL;
    use XML::Simple;
    use Data::Dumper;
    use constant TASK_ID => 6382;
    use constant CR_TYPE => '6382';
    use constant IMAGE_PATH => "/home/testco/public_html/files/";#"images/";
    
    sub new
    {
    my $class = shift;
    my $self = $class->SUPER::new(CR_TYPE, TASK_ID);
    bless $self, $class;
    
    my $url = 'http://www.onbip.com/xml/sunseeking9.xml';
    
    my $xml = $self->geturl('url'=>$url);
    $self->extract($xml);
    }
    
    sub extract{
    my $self = shift;
    my $xmlfile = shift;
    my $xml = new XML::Simple(ForceArray=>1,'KeyAttr' =>'image');
    my $data = $xml->XMLin($xmlfile);
    
    foreach(@{$data->{property}}){
        my $property = &makeScalar($_->ID->[0]);
        my $description = &makeScalar($_->{desc}->[0]->{en}->[0]);
    

    XML:

    <property>
    <id>226887</id>
    <desc>
     <en>
      Nice house in the center of Alhaurin de la Torre with walking distance to all amenities.
     </en>
     <es>
      Bonita casa mata en Alhaurin de la Torre con vistas a la montana, se puede acceder caminando al centro, colegios, etc.
     </es>
      <de>
        guter zustand, bezaubernde immobilie,
      </de>
      <fl>
        bon n acces par la route, partiellement meubl?a proximit?'?les, partiellement r?v
      ?fl>
    </desc>
    </property>
    

1 个答案:

答案 0 :(得分:0)

没有通用的方法来修复XML文件中的错误。您所能做的就是将文件拒绝为无效的XML。 The error handling documentation for XML::Simple解释说:

  

XML标准在不合规问题上非常明确   文档。解析任何单个元素时出错(例如a   缺少结束标记)必须导致整个文档被拒绝。

基本问题是这样的:一旦你允许文件包含错误,它就可以包含任何内容。没有办法解析它。实际上没有办法知道应该“纠正”什么。

如果由于某种原因,您的输入具有非常具体的,可预测的错误,您可以在将其传递给XML::Simple之前使用正则表达式检测到该错误。只要您知道一些特定的结束标记将包含??/而不是</,您可以执行以下操作:

my $xmlfile = shift;

my $xml = new XML::Simple(ForceArray=>1,'KeyAttr' =>'image');

#Try it to parse the file as is first.
my $data = eval { $xml->XMLin($xmlfile) };

#On error, try fixing.
if ($@)
{
    $xmlfile =~ s/\?\/?(desc|en|es|de|fl)>/<\/$1>/g;
    $data = eval { $xml->XMLin($xmlfile) };
    if ($@) 
    { 
        die "Failed to process the file even after attempting corrections: $@"; 
    }
}

以这种方式使用正则表达式有其危险性 - 您依赖于特定格式的输入XML。但是,通过首先尝试正常处理文件,至少可以最小化潜在的损害。这样,在文件失败的情况下,你只会冒一些风险。

更新:向第二次XMLIn()电话添加错误处理。

更新2:我更新了正则表达式以仅匹配提问者所需的确切案例(在这种情况下,最好尽可能具体,以避免误报匹配)。