Automatisierter Aufruf des W3C-Validators
Ob nun aus Kosten-, Bandbreiten- oder anderen Gründen: Es ist vorteilhaft, wenn man seine (X)HTML-Dokumente vor dem Hochladen auf den Server ohne viel Mühe "in einem Rutsch" validieren und/oder auf Wohlgeformtheit überprüfen kann.
Viele werden ohnehin eine Version des W3C-Validators lokal installiert haben. Wer nicht, findet sicher in folgenden Aneitungen, was er sucht:
- http://www.bjoernsworld.de/html/validator-offline.html
- http://lists.w3.org/Archives/Public/www-validator/2001OctDec/0194.html
Für diejenigen, welche keine Hinweise benötigen oder wollen:
Hinweis: Nutzer von Betriebssystemen oder Rechnerplattformen, welche nicht ein einzelnes "Newline" als Zeilenumbruch benutzen, laden sich am besten die .zip oder .gz Version herunter und überlassen dem Packprogramm die Konvertierung der Zeilenumbrüche.
- Download
- checkhtml.pl (4521 Bytes), checkhtml.pl.gz (1875 Bytes), checkhtml.zip (2000 Bytes)
- Listing
- Listing auf dieser Seite
Hinweise, Funktionsweise
Benötigte Module
Genutzt werden die Module LWP::UserAgent sowie HTTP::Request::Common. Diese Module sind Teil der Standard-Distributionen von Perl und werden auch für den Betrieb des W3C-Validators benötigt.
Validierung über die URI
Diese Möglichkeit bietet sich an, wenn die zu testenden Seiten auch über den lokalen Webserver erreichbar sind. Die Adresse der zu testenden Seite wird dabei als Parameter bei der GET-Anfroderung an den Validator übergeben und dieser holt sich die Seite selbst von der angegebenen Adresse.
Auf diese Weise kann auch eine Kopie der lokalen Dateien auf einem Server online getestet werden. Dazu müssen nur die Variablen für den "lokalen" Server ($localserv) und für das entsprechende Startverzeichnis ($localw3dir) entsprechend gesetzt werden.
Validierung per Upload
Sollten die Seiten nicht über den lokalen oder einen anderen Webserver erreichbar sein, können sie auch via Upload an den Validator übermittelt werden. Die zu validierende Seite wird dabei über eine POST-Anforderung zusammen mit dem Dateiinhalt an den Validator übermittelt.
Hinweis: Sollten die Dokumente keine zum Content-Type- und/oder Charset-Header äquivalente Informationen (wie etwa entsprechende Meta-Angaben im HEAD-Element oder eine XML-Deklaration enthalten), obwohl diese notwendig sind und diese Angaben sonst durch den Webserver geliefert werden, kann der Validator u.U. nicht richtig arbeiten.
Anzupassende Variable und Einstellungen
- Die erste Zeile...
... sollte den komplette Pfad zum ausführbaren Perl-Interpreter enthalten. Unter unix-artigen Systemen ist dies meist #!/usr/bin/perl -w oder #!/usr/local/bin/perl -w. Unter Windows könnte die erste Zeile #!C:/perl/bin/perl.exe -w lauten.
- $upload
Bei einem Wert von 0 wird das zu überprüfende Überprüfende Dokument via URI übermittelt, siehe Validierung über die URI. Ist der Wert gleich 1 (bzw. im Moment ungleich 0), erfolgt die Übermittlung des Dokumentes per Upload zum Validator, siehe auch Validierung per Upload.
- $releasedir
Enthält den absoluten (vollständigen) Pfad zu den lokalen Dokumenten. Das Slash ("/") am Ende nicht vergessen! Beispiel: C:/Eigene Dateien/www/testsite/
- $localw3dir
Der absolute (vollständige) Pfad zu den Dokumenten auf dem (lokalen) Webserver. Das Slash ("/") am Ende nicht vergessen! Beispiel: /, /~dirk/ oder /users/dirk/
- $localserv
Protokoll und Rechnername des (lokalen) Webservers. Angabe ohne abschließendes Slash ("/"). Beispiel: http://localhost oder http://intranet.nonamenoip.de.
- $validator
URI zum Validierungsprogramm des Validators. Beispiel: http://validator.w3.org/check oder http://validator.meinname.de/check
- $cr
Enthält die auf dem System gültige Zeichenkombination für einen Zeichenumbruch. Unix: \n, DOS, Windows: \n\r, Mac: \r
- $quiet
Wenn der Wert gleich 0 ist, werden keine Meldungen über Fortschritt und Ergebnisse der Prüfung der Dokumente ausgegeben. Bei einem Wert gleich 1 (im Moment ungleich 0) werden Meldungen ausgegeben. Beispielmeldung:
Beginn processing ----- Processing directory /exports/www/club2/users/dirk/ processing callerid.html o.k. done. processing games.html o.k. done. ... processing index.html Error done. processing checkhtml.html o.k. done. ... Processing directory /exports/www/club2/users/dirk/dwnl/ processing index.html o.k. done. ... ---- Finished: 29 files in 59 sec - 1 errors found.
- $html_regex
Regulärer Ausdruck zum Erkennen von zu überprüfenden Dokumenten. Mit folgendem Ausdruck werden Dateien mit den Endungen .htm, .html, .shtm und .shtml erkannt: ^([a-z0-9\-\_\.]*?)\.s?html?$. Um beispielsweise auch noch Dokumente mit den Endungen .php* oder .cgi abzurufen, wäre folgender Ausdruck notwendig bzw. möglich: ^([a-z0-9\-\_\.]*?)\.(s?html?|php.?|cgi)$.
- $useragent
Eine Kennung für den User-Agent der bei Abruf von Seiten als http-Header übermittelt wird. Eine Angabe von W3C_Validator/local führt zu einem Eintrag wie beispielsweise "W3C_Validator/local (libwww-perl/5.50)" in den Logbüchern eines Webservers. Praktisch, wenn man eigene Zugriffe aus den Statistiken herausfiltern will und den User-Agent-Header nicht fälscht oder unterdrückt,
Weiter Möglichkeiten und Hinweise
- Das Script gibt als Beendigungscode die Anzahl der gefundenen nicht validen Seiten zurück. Dies geschieht auch, wenn die Ausgabe der Erfolgs- oder Fehlermeldungen deaktiviert wurde.
- Wenn eine Seite nicht validiert, wird das Ergebnis des Valdidators in einer Datei, welche um die Endung ".err.html" erweitert wurde im selben Verzeichnis wie das überprüfte Dokument abgelegt. Diese zusätzliche Endung läßt sich genauso wie das Erstellen der Fehlerdateien selbst innerhalb des Scripts anpassen.
- Wenn die Upload-Funktion bei einer lokalen Installation nicht funktioniert, liegt der Fehler mit großer Wahrscheinlichkeit an der Konfiguration des eigenen lokalen (virtuellen) Web-Servers.
- Über Berichte hinsichtlich von Fehlern und/oder der Lauffähigkeit des Scripts unter verschiedenen OS, Rechner-Plattformen und Web-Server-Versionen würde ich mich freuen. Hinweise und Korrekturvorschläge sind auch gern gesehen.
Das Script
Das wird mir zu bunt: Listing ohne Syntaxhervorhebung
#!/usr/bin/perl -w
##
## This program is free software; you can redistribute it
## and/or modify it under the terms of the GNU General
## Public License as published by the Free Software Foundation
## (http://www.gnu.org/); either version 2 of the License, or
## (at your option) any later version.
##
## Author : Dirk Steinchen (dirk@atelier89.de)
## Webpage: http://www.atelier89.de/users/dirk/html/validator.html
## Version: 1.0
use strict;
use LWP::UserAgent;
use HTTP::Request::Common;
## edit this to your needs
## upload (post) files or get validation results
## via uri? 0=uri, 1=upload
my $upload = 0;
## absolute path to your local html files
## e.g. '/exports/www/testsite/' or 'c:/www/testsite/'
## don't forget the "/"
my $releasedir = '/exports/www/testsite/';
## absolute path to your files on local www-server
## e.g. '/testsite/' don't forget the "/"
my $localw3dir = '/testsite/';
## your local www-server
## don't insert the "/"
my $localserv = 'http://localhost';
## the validator listens here
my $validator = 'http://validator.w3.org/check';
## use "\n\r" for DOS/Win and "\n" for unix-like OS, "\r" for MAC
my $cr = "\n";
## Generate Output: 0=yes, 1=no
my $quiet = 0;
## mask for files we test, actually *.htm and *.html
my $html_regex = '^([a-z0-9\-\_\.]*?)\.html?$';
## name of the user-agent for testing, libwww version is appended later
my $useragent = "W3C_Validator/local ";
## edit lines below this line shouldn't be needed
## error-counter
my $errors = 0;
## file-counter
my $files = 0;
## start-time
my $time = time;
print $cr, $cr, "Beginn processing", $cr, "-----", $cr if $quiet == 0;
## process (and recurse) the given directory
process_directory($releasedir);
## statistics
$time = time - $time;
print "----", $cr, "Finished: $files files in $time sec" if $quiet == 0;
print " - $errors errors found.", $cr, $cr if $quiet == 0;
## return 0 if no errors otherwise the error-count
exit $errors;
sub process_directory {
my $directory = $_[0];
## internal var's
my (@subdir, @verzeichnis,
$key, $content, $ua, $req, $data, $file);
## read current directory
opendir (VERZEICHNIS, $directory) || die "$directory: $!".$cr;
@verzeichnis = readdir (VERZEICHNIS);
closedir (VERZEICHNIS);
print $cr, "Processing directory $directory", $cr if $quiet == 0;
## process each entry in directory list
foreach $key (@verzeichnis) {
## is current entry a html-file?
if ($key =~ /$html_regex/i) {
## if so, process this entry
print " processing\t$key\t" if $quiet == 0;
$data = $directory;
## if errors found, they go in this file
$file = $key.".err.html";
## create user-agent
$ua = new LWP::UserAgent;
## user agent's name
$ua->agent($useragent.$ua->agent);
## validation by uri oder upload?
if ($upload == 0) {
## get the resource name on local www-server
$data =~ s/$releasedir/$localw3dir/i;
## request for validation (get via uri)
$req = new HTTP::Request (
GET=>"$validator?uri=$localserv$data$key");
} else {
## request for validation (upload file)
$req = POST "$validator",
Content_Type => 'multipart/form-data',
Content => [
uploaded_file => [ "$data$key" ]
];
}
## result of validation
$content = $ua->request($req)->content;
## one more file...
$files++;
## write result to file
open (DATEI, "> $directory$file") || die $!;
print DATEI $content;
close (DATEI);
## valid/wellformed document?
if ($content =~ /No errors found\!/) {
## if so, clean up
print "o.k.\t" if $quiet == 0;
unlink "$directory$file";
}
else {
## if document is not valid, inc error-counter
## and leave file with results on disk
$errors++;
print "Error\t" if $quiet == 0;
}
## that's it for this page
print " done.$cr" if $quiet == 0;
} else {
## if directory entry is a subdir
if (-d "$directory$key") {
## save this entry for later processing
push (@subdir, $key)
}
}
}
## process subdir's in current directory
foreach $key (@subdir) {
## process only entrys that not refer to
## current (.) or upper (..) directory
if (!($key =~ /^\.*$/)) {
## process subdirectory (and recursivly it's subdirectorys)
process_directory ("$directory$key/");
}
}
}