2016-04-18 14 views
1

Ist es möglich, ein Perl-Skript zu verwenden, um HTML geordnete und ungeordnete Listen in kramdown zu konvertieren, wenn die Datei mehrere Listen beider Arten sowie anderen HTML-Code enthalten kann?Konvertieren von HTML-geordneten und ungeordneten Listen in kramdown

die Absicht verdeutlichen, so etwas wie die folgenden funktionieren könnte, wenn nur eine geordnete Liste und keine anderen Listen ist:

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

Oder könnte dies funktionieren, wenn es nur eine ungeordnete Liste und keine anderen Listen:

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

Ist es möglich, jede Liste im HTML-Dokument, zum Beispiel zu finden, und es zu einem Unterprogramm übergeben, die die Art der Liste bestimmen würden, wandeln sie es angemessen und zurück?

+0

Werfen Sie einen Blick auf http://search.cpan.org/~petek/HTML-Tree-3.23/lib/HTML/TreeBuilder.pm – xxfelixxx

Antwort

0

Im Allgemeinen sollten Sie keine regulären Ausdrücke verwenden, um HTML zu analysieren. Stattdessen sollten Sie einen HTML-Parser wie Mojo::DOM verwenden:

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> 

Ausgang:

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

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


- apple 
- pear 
- banana 
- pine apple 

</div> 

Das ist besser als ein regex, weil es leicht handhaben kann:

  • mehr <li> Elemente auf dem gleiche Linie
  • <li> Elemente, die mehr als eine Linie umfassen
  • Elemente mit Attributen
2

Der einfachste Weg wäre kramdown selbst zu verwenden, da es HTML analysieren kann und ein kramdown Dokument emittieren.

Mit der kramdown binary verwenden Sie einfach kramdown -i html -o kramdown INPUT.HTML.