1

如果文件可能包含两种类型的多个列表以及其他 HTML 代码,是否可以使用 Perl 脚本将 HTML 有序和无序列表转换为kramdown ?

为了说明意图,如果只有一个有序列表而没有其他列表,则类似以下内容可能会起作用:

$content =~ s!<\/ol>!!gis;
$content =~ s!<ol>!!gis;
$content =~ s!<\/li>!!gis;
$content =~ s!<li>!1. !gis;

或者,如果只有一个无序列表而没有其他列表,这可能会起作用:

$content =~ s!<\/ol>!!gis;
$content =~ s!<ol>!!gis;
$content =~ s!<\/li>!!gis;
$content =~ s!<li>!- !gis;

例如,是否有可能在 HTML 文档中找到每个列表,并将其传递给确定列表类型、适当转换并返回它的子例程?

4

2 回答 2

2

最简单的方法是使用 kramdown 本身,因为它可以解析 HTML 并发出 kramdown 文档。

使用 kramdown 二进制文件只需使用kramdown -i html -o kramdown INPUT.HTML.

于 2016-04-26T18:08:38.010 回答
0

通常,您不应该使用正则表达式来解析 HTML。相反,您应该使用像Mojo::DOM这样的 HTML 解析器:

use strict;
use warnings 'all';

use Mojo::DOM;

# Add the appropriate kramdown list marker to a Mojo::DOM node representing a
# single <li>, depending on whether it's in an <ol> or <ul>
sub add_list_marker {
    my ($node, $i) = @_;

    my $marker = $node->parent->tag eq 'ol' ? "$i. " : '- ';
    $node->prepend_content($marker);
}

# Convert a Mojo::DOM node representing an <ol> or <ul> to the corresponding
# kramdown
sub list_to_kramdown {
    my ($node) = @_;

    my $items = $node->children('li')->each(\&add_list_marker);
    my $text = $items->map('text')->join("\n");

    $node->replace("\n$text\n");
}

my $html = do {
    local $/;
    <DATA>
};

my $dom = Mojo::DOM->new($html);
$dom->find('ol, ul')->each(\&list_to_kramdown);
print $dom->to_string;

__DATA__
<h1>Leave surrounding HTML</h1>
<div id="including_enclosing_tags">
  <ol>
    <li>foo</li>
    <li>bar</li><li>baz</li>
    <li>qux</li>
  </ol>
  <ul>
    <li class="fruit">apple</li>
    <li>pear</li>
    <li>banana</li>
    <li>pine
        apple</li>
  </ul>
</div>

输出:

<h1>Leave surrounding HTML</h1>
<div id="including_enclosing_tags">

1. foo
2. bar
3. baz
4. qux


- apple
- pear
- banana
- pine apple

</div>

这比正则表达式更好,因为它可以轻松处理:

  • <li>同一行上的多个元素
  • <li>跨越多行的元素
  • 具有属性的元素
于 2016-04-20T23:26:27.613 回答