对结构化文本文件进行排序

时间:2015-05-21 12:54:52

标签: perl shell sorting latex princexml

我正在从LaTeX迁移到PrinceXML。我需要做的一件事就是转换参考书目。我已将.bib文件转换为HTML。但是,由于LaTeX负责为我分类条目,我没有注意将它们按正确的顺序排列 - 但在HTML中,声明的顺序很重要。

所以我的问题是:使用Linux命令行工具(例如Perl是可以接受的,但Javascript不是),我该如何对源文件进行排序:

<div id="references">
    <h2>References</h2>

    <ul>
        <li id="reference-to-book-1">
            <span class="ref-author">Sample, Peter</span>
            <cite><a href="http://example.org/">Online Book 1</a></cite>
            <span class="ref-year">2011</span>
        </li>
        <li id="reference-to-book-2">
            <cite>Physical Book 2</cite>
            <span class="ref-year">2012</span>
            <span class="ref-author">Example, Sandy</span>
        </li>
    </ul>
</div><!-- references -->

看起来像这样:

<div id="references">
    <h2>References</h2>

    <ul>
        <li id="reference-to-book-2">
            <span class="ref-author">Example, Sandy</span>
            <cite>Physical Book 2</cite>
            <span class="ref-year">2012</span>
        </li>
        <li id="reference-to-book-1">
            <span class="ref-author">Sample, Peter</span>
            <cite><a href="http://example.org/">Online Book 1</a></cite>
            <span class="ref-year">2011</span>
        </li>
    </ul>
</div><!-- references -->

标准是:

  1. 包含条目的<li>元素按照作者的字母顺序排序(即从一个<li id="到其对应的</li>的所有内容都将作为单个块移动。)
  2. 在每个条目中,元素按以下顺序排列:
    1. 行匹配class="ref-author"
    2. 行匹配<cite>
    3. 行匹配class="ref-year"
    4. 为了清楚起见,我在示例中省略了更多元素(例如class="publisher");另外,我经常遇到这个排序问题。因此,如果可以自由指定匹配的表达式(例如,作为脚本中的数组声明),将会很有帮助。
  3. 文件的其余部分(/id="references"/,/-- references --/之外)不变。
  4. 结果文件应该保持每一行不变,除了它在文件中的位置(这一点是因为我尝试的XML解析器打破了我的缩进)。
  5. 我使用sedsort解决了1,3和4问题,但无法通过这种方式获得2。

2 个答案:

答案 0 :(得分:2)

我为此使用了Mojo。之后您可能需要tidy up XML。

use Mojo::Base -strict;
use Mojo::DOM;
use Mojo::Util 'slurp';

my $xml = slurp $ARGV[0] or die "I need a file";

my $dom = Mojo::DOM->new($xml);

my $list = $dom->at('#references ul');

my $refs = $dom->find('li');

$refs->each('remove');

$refs = $refs->sort( sub { $a->at('.ref-author')->text cmp $b->at('.ref-author')->text } );

for my $ref ( @{ $refs } ){


    my $new = Mojo::DOM->new('<li></li>')->at('li');
    $new->append_content($ref->at('.ref-author'));
    $new->append_content($ref->at('cite'));

    #KEEP APPENDING IN THE ORDER YOU WANT THEM


    $list->append_content($new);

}

say $dom;

答案 1 :(得分:0)

我建议您使用XML::LibXML模块并将数据解析为HTML。然后,您可以根据需要操作DOM并将修改后的结构打印出来

这是一个如何运作的例子

use strict;
use warnings;

use XML::LibXML;

my $dom = XML::LibXML->load_html(IO  => \*DATA);

my ($refs) = $dom->findnodes('/html/body//div[@id="references"]/ul');

my @refs = $refs->findnodes('li');

$refs->removeChild($_) for @refs;

$refs->appendChild($_) for sort {
  my ($aa, $bb) = map { $_->findvalue('span[@class="ref-author"]') } $a, $b;
  $aa cmp $bb;
} @refs;

print $dom, "\n";


__DATA__
<html>
  <head>
  <title>Title</title>
  </head>
  <body>
    <div id="references">
        <h2>References</h2>

        <ul>
            <li id="reference-to-book-1">
                <span class="ref-author">Sample, Peter</span>
                <cite><a href="http://example.org/">Online Book 1</a></cite>
                <span class="ref-year">2011</span>
            </li>
            <li id="reference-to-book-2">
                <cite>Physical Book 2</cite>
                <span class="ref-year">2012</span>
                <span class="ref-author">Example, Sandy</span>
            </li>
        </ul>
    </div><!-- references -->
  </body>
</html>

<强>输出

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>Title</title></head><body>
    <div id="references">
        <h2>References</h2>

        <ul>

        <li id="reference-to-book-2">
                <cite>Physical Book 2</cite>
                <span class="ref-year">2012</span>
                <span class="ref-author">Example, Sandy</span>
            </li><li id="reference-to-book-1">
                <span class="ref-author">Sample, Peter</span>
                <cite><a href="http://example.org/">Online Book 1</a></cite>
                <span class="ref-year">2011</span>
            </li></ul></div><!-- references -->
  </body></html>