OriginalSeite    bei-ekke / HTML Tidy in Deutsch / Einführung zu TidyLib


Was hat es auf sich mit der 'TidyLib'?

'Tidylib' ist der klangvolle Name für die Bibliotheks-Version von Dave Raggett's beliebten HTML Tidy. Entscheidend für die Mutivation, daß Source Force Projekt "HTML Tidy" zu eröffnen, war, daß die aufrufbaren Bibliotheken von HTML Tidy wieder zur Verfügung stehen sollten. Obwohl das Kommandozeilen-Programm mächtig ist, ist es doch schwierig und uneffektiv es in andere Software zu integrieren.

Anforderungen

Wir haben verschiedene formlose Anforderungen für die Bibliotheken:

Dies können Sie hier erwarten

Die wahrscheinlich wichtigste Anforderung ist, daß sie leicht integrierbar sind. Die Adoption in C ist fast universell und eine C-Schnittstelle kann von vielen Programmiersprachen aufgerufen werden. Dies, der vorhandene Quell-Code in C und der bequeme Umgang mit C in der Entwicklermannschaft, waren der Ausschlag dafür, daß die öffentliche Schnittstelle der Bibliotheken in C gehalten werden.

Ein anderer Hauptgrund in der Planungsentscheidung, war die Verwendung unscharfer-Typen in der öffentlichen Schnittstelle. Dies erlaubt den Anwendungen eine Abarbeitung und reduziert den Aufwand diese in andere Programmiersprachen zu übersetzen.

Diese Strategie bewährte sich bereits. So konnten direkt wenig umfangreiche Umgebungen für C++, Pascal und
COM/ALT geschrieben werden. Auch war schnell eine Perl-Umgebung unter Verwendung von SWIG erstellt. SWIG-Umgebungen für Python, Ruby, Java und andere sollten auch möglich sein.

Nicht alles über Bord werfen

Im Ernst, Tidy muß Tidy bleiben! Es war und bleibt unakzeptabel neue Fehler einzubauen oder (viele) Funktionen zu entfernen. Am Ende erwiesen sich die vielen Test-Dokumente als unbezahlbaren Schatz für diese Arbeit.

AblaufStabilität / Ablaufinvarianz

Weil HTML Tidy vielfach genutzt wird - für die Inhalts-Überprüfung und zur Vorbereitung auf Umformung nach XHTML - , war es sehr wichtig es sowohl für Server-, als auch client-seitig Anwendungen verwendbar zu halten.

Diese Anforderung beinhaltet auch, daß die Bibliotheken immer gleich und unabhängig voneinander arbeiten, so daß sie von mehreren Anwendungen gleichzeitig mehrfach aufgerufen werden können.

Verfügbare Ein-/Ausgaben

Ein Teil der großen Integrations-Strategie, war die volle Trennung aller Ein-/Ausgaben (=I/O). Das bedeutet eine (relative) saubere Trennung zwischen Zeichen-Codierungs-Verarbeitung und dem Byte-weisen Datenaustausch. Intern liest die Bibliothek von der "Quelle" und schreibt in die "Ausgabe". Diese Trennung gilt für die "Web-Quellen" als auch für die Konfigurations-"Dateien". Die korrekte Implementierung unterstützt sowohl die Datei- als auch die Speicher-Ein/Ausgabe (=I/O). Andere Quellen und Ausgaben können dann über die öffentliche Schnittstelle unterstützt werden.

Gut wäre gewesen dies schon früher zu beachten. Besonders beachtenswert ist Marc-Andre Lemburg's mxTidy . Bei der Entwicklung einer Python-Umgebung für Tidy wandte Marc-Andre dieses Prinzip an und erstellte eine C Bibliothek. 'TidyLib' kann man als eine Vervollständigung/Weiterentwicklung Marc's Arbeit sehen.

Woher und wie bekommt man es?

Die Quellen holen

Am besten holt man sich die Quellen direkt über das CVS. Wenn Sie das CVS installiert haben, dann führen Sie folgende Befehle aus:

     C:\src> mkdir tidylib
     C:\src> cd tidylib
     C:\src\tidylib> set TIDYCVSROOT=:pserver:anonymous@cvs-pserver.sf.net:/cvsroot/tidy
oder C:\src\tidylib> set TIDYCVSROOT=:pserver:anonymous@cvs-pserver.sf.net:80/cvsroot/tidy
oder C:\src\tidylib> set TIDYCVSROOT=:pserver:anonymous@cvs-pserver.sf.net:443/cvsroot/tidy
oder C:\src\tidylib> set TIDYCVSROOT=:pserver:anonymous@cvs-pserver.sf.net:2401/cvsroot/tidy
     C:\src\tidylib> cvs -d %TIDYCVSROOT% login
     C:\src\tidylib> cvs -d %TIDYCVSROOT% export -R -r HEAD -dC:\src\tidylib Attic tidy

Wenn CVS nach dem Password fragt, dann einfach nur mit ENTER bestätigen. Die gleiche Vorgehensweise gilt für Unix-Varianten (auch Linux). Es müssen nur die entsprechende Verzeichnis-Trennzeichen geändert werden. Am besten man schreibt/kopiert sich obiges in eine Script/Batch-Datei.

Die Erstellung

Unix / GNU

Verwende build/gmake/Makefile für GNU gcc. Das normale Ziel ist all. Wird eine debug-fähige Erstellung benötigt, dann verwenden Sie das debug Ziel. Für andere Unix Compiler sollte das CC Macro durch den Compiler gewöhnlich durch cc angezeigt werden. Selbiges gilt für die große Zahl von Unix-Systemen, die "out of the box" als Klassisches Tidy unterstützen. Normalerweise erkennt Tidy automatisch das aktuelle Betriebssystem. Sollte dies nicht der Fall sein, dann liegt das an der platform.h. Sie können sie ändern und uns den Patch zusenden!

build/gmake/Makefile ist auch bei GCC/MinGW zu verwenden.

Ergänzend gibt es noch die Ziele clean und install. Sehen Sie sich erst das Makefile an und versichern Sie sich, welche ausführbaren Programme, Header und Bibliotheken sie für die Verwendung vom install-Ziel benötigen.

Standardmäßig sind dies /usr/bin, /usr/include und /usr/lib. Diese Macros müssen im Makefile für Ihre Installation angepasst werden.

make all

Windows / Visual C++

Verwende msvc/Makefile.vc6 für VC++ in der Kommando-Zeile oder build/msvc/tidy.dsw in der IDE (=EntwicklungsUmgebung). Der Name läßt erkennen, daß dies für Visual C++ 6.0 getestet ist. Das Service Pack 3 oder höher wird empfohlen. Dabei stehen die Ziele all, clean, all DEBUG=1 und clean DEBUG=1 zur Verfügung.

nmake /f Makefile.vc6 all erzeugt das Release(=die Ausgabe)
nmake /f Makefile.vc6 clean löscht das Release
nmake /f Makefile.vc6 all DEBUG=1 erzeugt eine Debug-Version
nmake /f Makefile.vc6 clean DEBUG=1 löscht die Debug-Version

Sollten Sie Visual C++ 6.0 nicht im Standard-Verzeichnis installiert haben, dann müssen Sie zunächst die VCVARS32.BAT anpassen. Die Makefile.vc6 liefert nur die Compilierung und funktioniert z.B. bei clean nicht ganz korrekt. Diese Makefile.vc6 funktioniert und ist reichlich mit deutschen Kommentaren versehen, so daß man sich die Compilier-Optionen für's Projekt "abgucken" kann.

GNU AutoConf/AutoMake

Für die Aktivierung des "GNU AutoConf tool set" wurde die Eingabedatei ergänzt. Eine Anleitung, wie GNU für die Erstellung von Werkzeugen mit Tidy zu verwenden ist, finden Sie in build/gnuauto/readme.txt.

Beispiel

Zum bessern Verständnis, wie Tidy aufzurufen ist, ist wohl ein Beispielprogramm, was Tidy verwendet, am besten geeignet. Grundlage ist das Wissen darüber, welche Rückgabe-Zahl der API-Funktion, was bedeutet:

0 == Erfolgreich (Fehler- und Warnungs-frei)
Alles bestens!
1 == Warnungen und keine Fehler
Prüfe den Fehler-Zwischenspeicher oder verfolge die Fehler-Meldungen für Einzelheiten.
2 == Fehler und Warnungen
Standardmäßig erzeugt Tidy keine Ausgabe. Man kann die Ausgabe aber mit der force-output Option erzwingen. Allerdings mit dem Hinweis, daß die Einzelheiten mit dem Fehler-Zwischenspeicher oder durch Verfolgen der Fehlermeldungen geklärt werden müssen.
<0 == Schwerwiegender Fehler
Eben die üblichen System-Fehler, wie sie in <errno.h> definiert sind.
z.B. sind diese Fehler in:
D:\Programme\Microsoft Visual Studio .NET\Vc7\crt\src\errno.h
D:\Programme\Microsoft Visual Studio .NET\Vc7\include\errno.h

identisch definiert und dessen Bedeutung kann über die IDE-Hilfe ermittelt werden.
z.B.: in :
ms-help://MS.VSCC/MS.MSDNVS.1031/vclib/html/_mfc_CFileException.3a3a.m_cause.htm

Standardmäßig werden die Warn- und Fehler-Meldungen an stderr gesendet. Durch die Funktionen tidySetErrorFile() oder tidySetErrorBuffer() , wie sie in tidy.h beschrieben sind, kann dieses Verhalten geändert werden.


/* libintro.c
   entsprechend http://tidy.sourceforge.net/libintro.html
   und .\include\tidy.h
*/
#include <stdio.h>
#include <errno.h>

#include "tidy.h"
#include "buffio.h"

int main(int argc, char **argv )
{
  const char* input = "<title>Irgendwas</title><p>Irgendwas!";
  TidyBuffer output = {0};
  TidyBuffer errbuf = {0};
  Bool ok;
  int rc = -1;

  TidyDoc tdoc = tidyCreate();                                  /* Das "Document" initialisieren */
  printf( "Säubere:\t%s\n", input );

  ok = tidyOptSetBool( tdoc, TidyXhtmlOut, yes );               /* Konvertierung nach XHTML */
  if (   ok    ) rc = tidySetErrorBuffer( tdoc, &errbuf );      /* Erfassen der Fehlerdiagnosen */
  if ( rc >= 0 ) rc = tidyParseString(    tdoc, input );        /* Analysiere die Eingabe */
  if ( rc >= 0 ) rc = tidyCleanAndRepair( tdoc );               /* Bereinige es! */
  if ( rc >= 0 ) rc = tidyRunDiagnostics( tdoc );               /* Kvetch */
  if ( rc >  1 ) rc = ( tidyOptSetBool(   tdoc, TidyForceOutput, yes) ? rc : -1 ); /* Bei einem Fehler die Ausgabe erzwingen. */
  if ( rc >= 0 ) rc = tidySaveBuffer(     tdoc, &output );      /* gut formatieren */
  if ( rc >= 0 )
  { if ( rc > 0 ) printf( "\nFehlerdiagnose:\n\n%s", errbuf.bp );
    printf( "\nUnd hier das Ergebnis:\n\n%s", output.bp );
  }
  else
    printf( "Ein schwerwiegender Fehler (%d) ist aufgetreten.\n", rc );

  tidyBufFree( &output );
  tidyBufFree( &errbuf );
  tidyRelease( tdoc );
  return rc;
}

Bemerkungen zur Anwendung

Selbstverständlich gibt es auch Funktionen zum Analysieren und Speichern der Quelltextauszeichnungs- und Konfigurations-Datei. Ebenfalls ist es möglich andere und neue Eingabe-Quellen bzw. Ausgaben zu erstellen. Zum Beispiel könnte die Quelltextauszeichnung von einer URL geladen werden.

Man denke daran, daß eine Anwendung beliebig viele Dokumente und Speicherobjekte initialisieren kann. Sie sind aber relativ leicht zu initialisieren (nur der wenige wirklich benötigte Speicher wird angefordert und wieder freigegeben, also fast bei null - wirklich!) und zu zerstören; sie können also lokal erstellt und zerstört werden, wie es gerade benötigt wird. Ebenso gibt es keine Probleme sie über eine Weile aufzubewahren (im Speicher zu halten). Zum Beispiel könnte sich eine Server-Anwendung einmal globale Konfigurations-Daten halten. Werden dann Dokumente analysiert, können diese Konfigurations-Daten zum entsprechendem Dokument kopiert werden, siehe tidyOptCopyConfig. Aber eigentlich ist mit der Initalisierung der globalen Konfigurations-Daten zu Beginn keine Synchronisation mehr nötig!

Was noch zu tun ist?

Bevor es TidyLib gab, gab es noch einige Augaben zu kompletieren.

Die API Dokumentation

Letzlich sind wir auf die Verwendung von Doxgen gestossen, um gute Dokuemntationen in HTML, direkt von Datei-Kopf-Kommentaren, erstellen zu können.

Nächtliche Aktualisierungen/Erstellungen

Diese benötigten wir für die Erstellungen der Source-Forge-Compile-Fram- Erstellungen, den Erstellungen der Bibliotheken und der Kommando-Zeilen-Programme.

Aussichten

Die Tinte ist noch nicht trocken und schon benötigen all die Leute mehr! Gut - was wird erwartet? Verschiedene Ideen wurden dazu in der Entwickler-eMail-Liste diskutiert.

Zeichen Codierung

Moemetan, sind alle Zeichen-Codierungen fest in der Bibliothek integriert. Das bedeutet, mühselig unterstützen wir viele der bekannten Codierungen wie GB2312, euc-kr, Ost-Europäische Sprachen, Kyrilisch usw. Einige dieser Sprachen müssen erst nach ISO-10646/Unicode transformiert werden, bevor Tidy mit ihnen arbeiten kann.

Zwei Ansätze wurden vorgeschlagen: Die einfache Verwendung von Zeichen oder eine angeglichene Version der aufrufbaren Bibliothek XML::Encoding von Clark Coopers. Angesicht dessen, sind die Zeichen vorzuziehen. Denn, es ist GPL, obwohl, dies mit der Lizenz unverträglich sein kann. Außerdem sind es Transkriptions-Ausgaben ähnlich Bif5 und anderer CodeSets, die mehr oder minder durch Zeichen repräsentiert werden. Die XML::Encoding nutzt die "Perl Artistic License" und unterstützt ausdrücklich alle alternativen Transkriptionen für Big5 und anderer. Mehr Informationen dazu kann man unter CPAN und "Tidy Ausgaben" finden.

Die Fehler-Behandlung

  • kategorisierte Fehler
  • Verbesserung der Meldungs-Lokalisierung
  • Verbesserung der seperaten Syntaxanalyse und Diagnose

Inhalts Model

  • Pro-Element-und-Version Attribut Unterstützung
  • DTD Interne-Untermengen Unterstützung
  • Modulare XHTML Unterstüzung (XHTML 1.1)

Seite zuletzt aktualisiert am 26 November, 2002 von C. Reitzel


Der Autor distanziert sich ausdrücklich vom Inhalt aller externen Links und Verweise.
Er übernimmt keine Gewähr oder Haftung für
Vollständigkeit, Richtigkeit, Aktualität oder etwaige Schäden.