2013-06-28 141 views
0

试图使用Perl在标签之间提取数据。不幸的是,解析器是不是一种选择这里,是因为:从文件中提取标签之间的数据

  1. 我需要有标准的代码来对目录中的许多文件运行。
  2. 我需要提取的内容在不同的文件中有所不同。例如:“纳入标准”在一个文件中是<P>,另一个文件中是<L>,第三个文件中是<TD>

所以,我真的没有办法,只能用一种非常糟糕的方式来使用正则表达式来解析文件并提取数据。除非有人有更好的主意......

这就是说,我有下面的代码做一个搜索和提取一个文件。

对于给定的短语,我需要提取下面的内容,它可以是一个段落或列表<L>

所以这是我在做什么:

  • 打开文件
  • 包含短语行查找。
  • 检查下一行是否以<L>标记开头,提取<L></LI>标记之间的所有内容(行范围)。

以下是我的部分代码。这不会返回任何内容。所以,在这里寻找一些帮助。

  1. 我在正确的轨道上吗?
  2. 我怎样才能提取<L></L>标签之间的全部数据,并将其存储在数组中进行计数?

代码片段:

if (($curr_line =~ m/\binclusion criteria\b/i) 
    && ($curr_line !~ m/\b....\b/) && ($curr_line !~ /^<Bookmark/)) 
{ 
    $nextline = <$CURR_FILE> 
    if ($next_line =~ /^<L/) 
    { 
     print "next line is a list\n"; 
     ## inclusion is a list..so extract everything from the list 
     my $start = "<LI>"; 
     my $end = "</L>";   
     while ($next_line =~ m{($start.*?$end)}gx) 
     { 
      print "List is...$next_line"; 

     }   

    }#inner if 
    } 

编辑:添加输入XML片段。

所以这里是从PDF生成的XML文件之一。

我需要提取:“这是研究目的内容”。如果只有路径在所有文档中保持一致,将会很容易。这是在://Sect//H4但在其他下它是在//Sect//H2//Sect//H1。这里没有一致性。

还需要提取所有列出的内容和条件。同样的问题。文档之间的路径不一致。

书签链接导致段落内容不相关。

有了这种不一致的XML,如果我仍然可以使用1个解析器程序从数千个文档中提取信息,则完全不同。唯一的原因是我要使用可怕的漏洞和效率极低的搜索和提取程序,这是因为XML文档中的不一致。

<?xml version="1.0" encoding="UTF-8" ?>                
<TaggedPDF-doc> 
    <bookmark-tree> 
    <bookmark title="5.1.1 Inclusion criteria"> 
     <destination structID="LinkTarget_1130"/> 
    </bookmark> 
    <bookmark title="5.1.2 Exclusion criteria"> 
     <destination structID="LinkTarget_1131"/> 
    </bookmark> 
    </bookmark> 
    <Part> 
    <Sect> 
     <Sect> 
     <H4>2.1 Study purpose </H4> 
     <P>This is study purpose content</P> 
     </Sect> 
     <P id="LinkTarget_1130"> This is some unrelated paragraph </P> 
     <P>5.1.1 Inclusion criteria </P> 
     <L> 
     <LI> 
      <LI_Label>1. </LI_Label> 
      <LI_Title>Title 1</LI_Title> 
     </LI> 
     <LI> 
      <LI_Label>2. </LI_Label> 
      <LI_Title>Title 2 </LI_Title> 
     </LI> 
     </L> 
     <P>some content 1</P> 
     <P>some content 2</P> 
     <P>some content 3 </P> 
     <P>some content 4</P> 
     <P>some content 5</P> 
     <L> 
     <LI> 
      <LI_Label>4.</LI_Label> 
      <LI_Title>Title 4</LI_Title> 
     </LI> 
     <LI> 
      <LI_Label>5. </LI_Label> 
      <LI_Title>Title 5 
     </LI> 
     </L> 
     <P id="LinkTarget_1131"> This is some unrelated paragraph </P> 
     <P>5.1.2 Exclusion criteria </P> 
     <P>Some content 1</P> 
     <L> 
     <LI> 
      <LI_Label>1. </LI_Label> 
      <LI_Title>Title 1</LI_Title> 
     </LI> 
     <L> 
      <LI> 
      <LI_Label>2. </LI_Label> 
      <LI_Title>Title 2</LI_Title> 
      </LI> 
      <LI>(3) some content</LI> 
     </L> 
     <P>Some content </P> 
     </Sect> 
    </Sect> 
    </Part> 
</TaggedPDF-doc> 
+3

因此,您不应该使用真正的解析器,而应该开发一些*因为这将是标准的? –

+0

请显示每个XML文件的简短示例。这可以通过解析器完成,没有问题。 – simbabque

+3

解析器在这里不是一个选项,解析器在这里是一个解决方案。 –

回答

1

您的要求是稍有矛盾,但我相信,像

(//Sect//H1 | //Sect//H2 | //Sect//H3 | //Sect//H4)[1]/following-sibling::* 

XPATH表达式可以做你想做的。当你的“XML”的清理后的版本,例如

use strict; use warnings; use 5.010; use XML::LibXML; 

my $dom = XML::LibXML->load_xml(IO => \*DATA); # XML is in DATA file handle 

say $dom->findvalue('(//Sect//H1 | //Sect//H2 | //Sect//H3 | //Sect//H4)[1]/following-sibling::*'); 

运行输出

This is study purpose content 
+0

这可以用于这个特定的值。但是,如果我想提取:5.1.1纳入标准和动态下的所有儿童,我怎么知道应该在哪里停止?我只需要检索

之间的所有内容5.1.1纳入标准

5.1.2纳入标准

BRZ

+1

@simak然后您应该发布更多示例(删除不必要的行) –

2

错误。如果不使用正确的XML解析器,就不应该读取XML,而且XML的复杂性和可变性也会加强这种情况。

很明显,如果根本没有数据模式,那么无论使用哪种编程语言,都无法提取任何有用的东西。但是你必须认为它有某种模式,否则你不会尝试这个任务。所以你需要告诉我们这种模式是什么。例如,如果你想第一个元素名称以“H”后的第一个下列元素,这将是

//*[starts-with(name(), 'H')][1]/following-sibling::*[1] 

不管是什么规则,如果你可以用英语表达出来,那么你可以在XPath中表达出来(或者如果事情变得非常棘手,在XSLT或XQuery中)。

坦率地说,我认为你的困难在于你试图用代码破解它,当你没有想到你想要实现的规则。这注定会在任何编程语言中失败。

相关问题