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 文件之一。

我需要提取:“这是学习目的内容”。如果只有路径在所有文档中保持一致,那将很容易。这里是 under://Sect//H4但在其他情况下是//Sect//H2or //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>
4

2 回答 2

2

错误的。如果不使用适当的 XML 解析器,您永远不应该阅读 XML,而且您的 XML 复杂且多变的事实更加强化了这种情况。

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

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

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

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

于 2013-06-28T16:46:10.177 回答
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
于 2013-06-28T13:51:42.157 回答