我知道這看起來像火焰誘餌,但事實並非如此。聽我說。因爲stackexchange更喜歡問題(這主要是一個答案),讓我問「以下哪些問題?」正則表達式在Perl中解析XML或XHTML DOM
正則表達式不適合DOM解析。但是,當可用時,與複雜的DOM解析器相比,它們具有很好的通用性,易用性,並且沒有額外的學習曲線。
所以,我想我會分享一個黑客,使正則表達式適合快速和骯髒的DOM變化。它將臨時gid添加到html標籤及其關閉屬性中,然後使用正則表達式返回引用。
該代碼是仁慈短小的,並且符合perl哲學之一,即如果編程時間比運行時短,某些解決方案可能會更好。
#!/usr/bin/perl -w
use strict;
use warnings FATAL => qw{ uninitialized };
################################################################
sub tokenize {
my $GLOBAL; (defined($_[0])) and do { $GLOBAL = $_; $_ = $_[0]; };
my @xmlstack;
my $gid=0;
my $addgid= sub {
my ($s,$e) = @_;
($e =~ /\/$/) and return "<$s$e/>"; ## could add gid here, too.
if ($s =~ /^\/(.*)/) {
my $off= pop(@xmlstack);
($off->[0] eq $1) or die "not a valid document at id=$gid. (wanted = $off->[0] . had = $s).\n";
return "<$s gid=\"".($off->[1])."\">"; ## not legal html now, but easy to remove
} else {
push(@xmlstack, [$s, ++$gid]);
return "<$s gid=\"$gid\">";
}
};
my $U="#!#";
(/$U/) and die "sorry, this is a hack. pick any other unique string than '$U'\n";
s/<!--(.*?)-->/$U$1$U/gms; # comments can contain html tags
s/\<(\/?[a-zA-Z0-9]*)(.*?)\>/$addgid->($1,$2)/emsg;
s/$U(.*?)$U/<!--$1-->/gms;
(@xmlstack) and die "unfinished business: ".pop(@xmlstack)->[0]."\n";
if ($GLOBAL) { my $CHANGED= $_; $_ = $GLOBAL; return $CHANGED; } else { return $_; }
}
sub untokenize {
my $GLOBAL; (defined($_[0])) and do { $GLOBAL = $_; $_ = $_[0]; };
s/ gid="[0-9]+">/>/g; ## buglet: could mistakenly remove gid from inside comments.
if ($GLOBAL) { my $CHANGED= $_; $_ = $GLOBAL; return $CHANGED; } else { return $_; }
}
################################################################
$_ = "<html>\n<body>\n
<p> <sup>a</sup><sub>b</sub>. </p>.
<hr />
<p> hi<sup>u<sub>ud<sup>udu</sup></sub></sup> </p>.
</body>
</html>
";
tokenize();
## now we can use regex using backreferences
while (/<sup (gid="[0-9]+")>(.*)<\/sup \g1>/gms) {
print "Example matching of all sup's: $1 $2\n"; ## could call recursively
}
## another example: add a class to sup that is immediately followed by a sub
s/\<sup (gid="[0-9]+")\>(.*)<\/sup \g1>\s*\<sub/<sup class="followed" $1>$2<\/sup $1><sup/gms;
print untokenize($_);
這很可能還是無知HTML併發症的整體轉換,但它可以處理大量的DOM XHTML和XML的工作,否則不適用於正則表達式解析。
'/ \ <(\ /〔A-ZA-Z0-9] *)(。*?)\> /'是不正確的。使用現有工具的原因是不是因爲正則表達式是不好的,這是因爲它是很多工作的地獄來寫自己的解析器,而不是使用現有的(使用正則表達式或其他)。 – ikegami
它可以在xhtml上失敗的示例?我正在查看html標籤列表,這應該在有效的html上工作......當然,它太寬鬆了。 –
我明確未說明頂撞你的要求,它更容易寫自己的解析器比學習現有的一個。 – ikegami