从文件中提取标签之间的数据

时间:2013-06-28 10:30:53

标签: xml perl

尝试使用Perl在标记之间提取数据。不幸的是,解析器不是一个选项,因为:

  1. 我需要有标准代码才能对目录中的许多文件运行。
  2. 我需要提取的内容在不同的文件中有所不同。例如:“包含条件”在一个文件中为<P>,在另一个文件中为<L>,在第三个文件中为<TD>
  3. 所以,我真的没有选择,只能使用一种非常流行的方式来使用正则表达式来解析文件并提取数据。除非有人有更好的主意......

    那就是说,我有以下代码在文件中进行搜索和提取。

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

    所以这就是我在做的事情:

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

    以下是我的部分代码。这不会返回任何东西。所以,在这里寻求帮助。

    1. 我是否正确地走这条路?
    2. 如何在<L></L>代码之间提取整个数据并将其存储在数组中进行计数?
    3. 代码片段:

       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之下。这里没有一致性。

      还需要在inlcusion和exlcusion标准下提取所有列出的内容。同样的问题。跨文档的路径不一致。

      书签链接指向包含不相关内容的段落。

      如果使用这种不一致的XML,如果我仍然可以使用1解析器程序从数千个文档中提取信息,那么就没有了。我使用可怕的kludgy和极其低效的搜索和提取程序的唯一原因是因为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>
      

2 个答案:

答案 0 :(得分:2)

错误。如果不使用正确的XML解析器,就不应该阅读XML,而且XML复杂多变的事实可以进一步增强案例。

显然,如果数据根本没有模式,那么无论使用何种编程语言,都无法提取任何有用的内容。但你必须认为它有某种模式,否则你就不会尝试这项任务。所以你需要告诉我们这种模式是什么。例如,如果您希望在名称以“H”开头的第一个元素之后的第一个跟随元素,那将是

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

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

坦率地说,我认为你在这里遇到的困难是当你没有考虑到你想要实施的规则时,你正试图用代码破解它。这注定要在任何编程语言中失败。

答案 1 :(得分:1)

您的请求有点矛盾,但我相信像

这样的XPATH表达式
(//Sect//H1 | //Sect//H2 | //Sect//H3 | //Sect//H4)[1]/following-sibling::*

可以做你想做的事。在“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