Thread Platzhalter für HTML-Ausdrücke (reguläre Ausdrücke)
(47 answers)
Opened by vitopetre at 2010-04-02 09:42
ich habe mal aus Neugier einen kleinen Parser geschrieben. Er ist weder Perfekt noch mit anderen Modulen zu vergleichen! Es ist nur eine Machbarkeitsstudie. Es ist nicht für den normalen Gebrauch geeignet.
Also nach all den Warnungen: Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 #!/usr/bin/perl use strict; use warnings; use Data::Dumper; use LWP::Simple; my $file=shift; my $data=''; if($file=~m!^http://!) { $data=get($file); } elsif(-f $file) { $data=eval{local($/,@ARGV)=(undef,$file); <>}; } elsif($file eq '-') { local $/=undef; $data=<STDIN>; } else { $data=$file; } print Dumper(parse($data)); ######################################################################## sub parse { # Liste mit allen Single-Tags my @single=qw( br hr ); # Abschuss-Tag erzwingen my %optional=( li=>[qw(ul ol)] td=>[qw(tr th)]); my $data=shift || ''; my $tree={name=>'root',childs=>[],opts=>{}}; my @deep=({name=>'root',ref=>$tree}); #Sind überhaupt html-tags enthalten? return undef if($data!~m!</?[\w\-_]+\s*(?:[\w\-_]+\s*=\s*(?:"[^"]*"|'[^']*'|[^<>]*)\s*)*\s*?/?>!s); # alle Tags finden und bearbeiten while($data=~m#<(/?[A-Za-z0-9][\w\-_]+)\s*((?:[\w\-_]+\s*=\s*(?:"[^"]*"|'[^']*'|[^<>]*)\s*)*)\s*?(/?)>((?:<!--.*?-->|[^<>]*)*)#gcs) { my $name=lc($1); my $opts=$2; my $single=$3; my $text=$4; my $end=0; # Single-Tag erzwingen $single=1 if(grep{lc($_) eq lc($name)}@single); $text=~s/^\s*(.*?)\s*$/$1/gs; # es handelt sich um einen Abschluss-Tag if(substr($name,0,1) eq '/') { # / entfernen substr($name,0,1,''); # Schon letzter end-tag last unless(@deep>1); # Passenden Abschluss-Tag finden while(my $p=shift(@deep)) { last if($p->{name} eq $name); } # keinen passenden gefunden last unless(@deep); # Block als Singeltag verarbeiten $single=1; $end=1; } # Abschusstag erzwingen if(exists($optional{$name}) && @deep>0) { my $cnt=1; while($cnt<@deep) { last if(grep{$deep[-$cnt]->{name} eq $_}@{$optional{$name}}); $cnt++; } $end=-$cnt; } # es ist kein Abschluss-Tag if($end<1) { # neuen Eintrag Erzeugen my $ref={name=>$name,childs=>[],opts=>{}}; push(@{$deep[$end]->{ref}->{childs}},$ref); # wir haben keine Single-Tag unshift(@deep,{name=>$name,ref=>$ref}) if(!$single); # Optionen Parsen if($opts) { while($opts=~s!(\w+)\s*=\s*"([^"]*)"!!s) { $ref->{opts}->{$1}=$2; } while($opts=~s!(\w+)\s*=\s*'([^']*)'!!s) { $ref->{opts}->{$1}=$2; } while($opts=~s!(\w+)\s*=\s*(\S*)!!s) { $ref->{opts}->{$1}=$2; } } } push(@{$deep[0]->{ref}->{childs}}, $text) if($text); } return $tree; } XHTML wird ohne Probleme geparst. Bei HTML fehlen viele Ausnahmeegelungen Edit: Ist mir gerade aufgefallen, dass der RegExp nicht mit HTML-Kommentaren klar kommt. Habe ich eben ergänzt. Last edited: 2010-04-06 16:38:37 +0200 (CEST) |