HomeReiseberichteGartenPhotographieComputerDies und Das

Websitegestaltung mit Forrest

Index für eine Website

nach obenWie der Berg zum Propheten kommt

Nachdem die Reiseberichte zu Schottland immer stärker wuchsen, kam bei uns der Wunsch auf, diese Berichte nicht nur chronologisch zu organisieren. Uns kamen vor allem zwei Übersichten in den Sinn:

Es stellt sich nur die Frage, wie man dies aufbauen soll, ohne dir Referenzen mit Tippfehlern und Ungenauigkeiten unbrauchbar zu machen. Es wäre sicherlich am Einfachsten, wenn man in der XML-Seite von Forrest mit folgender Zeile auskäme:

				
  <expandindex file="themenindex.xml" />
			

Dazu gehören zwei Bauteile:

  1. Ein Parser, der eine passende XML-Struktur schreibt, die an diese Stelle des Dokuments eingefügt wird.
  2. Eine Erweiterung der XSL-Transformationen, mit denen das generierte Dokument integriert und entsprechend den Wünschen formatiert wird.

nach obenEin Parser für die Referenzen

Eine Warnung vorab: der Code für den Parser ist extrem an unsere Bedürfnissen angepasst und wird nur in seltenen Fällen für jemand anderen einfach wiederverwendbar sein. Wer möchte, kann sich den Sourcecode gerne anschauen und seinen Wünschen entsprechend anpassen.

In der Folge ein paar kurze Informationen, wie ich das Problem gelöst habe:

nach obenDurchsuchen der XML-Sourcen

Eines der häufigsten Probleme, das bei einem größeren Projekt auf einen zukommt, ist, an die Liste der zu bearbeitenden Files zu kommen. Ant ist für diese Arbeit wie geschaffen, da es schon vorgefertigte Klassen anbietet, die mit Listen von Files arbeiten.

build.xml

					
  <refbuilder basedir="${src.dir}"
              destdir="${dest.dir}"
              includes="reiseberichte/schottland*/*.xml"
              excludes="**/book.xml">
  </refbuilder>
				

RefBuilderTask.java

					
  public class RefBuilderTask extends MatchingTask
  {
    private File basedir;
    private File destdir;

    public void execute() throws BuildException
    {
      verifyValues();
      DirectoryScanner ds = getDirectoryScanner(basedir);
      String[] files = ds.getIncludedFiles();
      ...
    }

    public void setBasedir(File basedir)
    {
      this.basedir = basedir;
    }
    
    public void setDestdir(File destdir)
    {
      this.destdir = destdir;
    }
  }
				

Mit dem geringen Aufwand erhält man einen Array von Strings, der die relativen Pfade und Namen zu den zu parsenden XML-Files enthält.

nach obenFinden der Index-Tags

Das Parsen von XML ist an sich eine problemlose Angelegenheit. Es gibt für diesen Zweck den DOM- und den SAX-Parser. Ich bevorzuge für diese einfachen Probleme den SAX-Parser, weil mich die tatsächliche Struktur nur begrenzt interessiert - der Parser soll nur mitbekommen, wenn das passende Tag in der XML-Source auftaucht.

					
  <index entry="National_Driver_Information_and_Control_System" />
				

Das Tag hat eine einfache Struktur ohne Inhalt. Der Text des Attributs entry wird mit Unterstrichen getrennt, damit man den Text auch für <a name="..."> nutzen kann, wenn an eine bestimmte Stelle innerhalb der Seite gesprungen werden soll.

Für den Handler des SAX-Parser muss man im Sourcecode selbst nachschauen, aber es sei hier gesagt, dass der Parser mit einer ziemlichen Menge Kommentaren nur um die 200 Zeilen lang ist - also beim besten Willen nicht zu kompliziert für jemanden, der schon einmal Java gesehen hat.

nach obenStruktur der Index-Daten

Die Möglichkeiten von XSL sind begrenzt. Deswegen sind die Index-Daten recht mundgerecht für die Darstellung. Es war von Anfang an klar, dass der Index auf jeden Fall Einsprungpunkte haben muss, um bei größeren Indices zumindest zu einem Buchstaben springen zu können. Damit ergab sich eine Struktur wie folgt:

				
  <?xml version="1.0" encoding="iso-8859-1"?>
  <index>
    <letter name="A">
      <entry name="Abendstimmungen" shortname="Abendstimmungen">
        <reference source="/.../e_nach_islay.html#idx_Abendstimmungen" title="Abendfähre..." />
      </entry>
    </letter>
  </index>
			

Der Index ist nach Buchstaben (letter) und Einträgen (entry) strukturiert. Zu jedem Eintrag können mehrere Referenzen zu den Reiseberichten existieren. Diese Daten sind genauso, wie sie für den Aufbau des Index' benötigt werden.

nach obenXSL zur Tranformation der Index-Daten

Die benötigten Erweiterungen sind wieder in dem File document-to-html.xsl vorzunehmen.

				
  <!-- 
    Index
  -->
  <xsl:template match="expandindex">
    <xsl:variable name="file" select="concat('../../../../crossrefs/',@file)" />
    <xsl:apply-templates
     select="document($file)/index"
     mode="insertindex" />
  </xsl:template>

  <xsl:template match="index" mode="insertindex">
    <div class="indexletters">
      <xsl:for-each select="letter">
        <xsl:choose>
          <xsl:when test="position()=1"></xsl:when>
          <xsl:otherwise>·</xsl:otherwise>
        </xsl:choose>
        <xsl:call-template name="indexletter" />
      </xsl:for-each>
    </div>
    <xsl:apply-templates select="letter" mode="insertindex" />
  </xsl:template>

  <xsl:template name="indexletter">
    <a href="#{@name}">
      <xsl:value-of select="@name"/>
    </a>
  </xsl:template>
  

  <xsl:template match="letter" mode="insertindex">
    <h3>
      <span class="toplink">
        <a href="#top">
          <img src="/skin/images/nav_top.gif" class="navimg"
           alt="nach oben" title="nach oben" />
        </a>
      </span>
    <a name="{@name}" /><xsl:value-of select="@name" /></h3>
    <xsl:apply-templates select="entry" mode="insertindex" />
  </xsl:template>

  <xsl:template match="entry" mode="insertindex">
    <dl class="idxentry">
      <dt>
        <a name="{@shortname}"><xsl:value-of select="@name" /></a>
      </dt>
      <dd>
        <ul>
          <xsl:apply-templates select="reference" mode="insertindex" />
        </ul>
      </dd>
    </dl>
  </xsl:template>

  <xsl:template match="reference" mode="insertindex">
    <li>
      <a href="{@source}"><xsl:value-of select="@title" /></a>
    </li>
  </xsl:template>
			

Hier wird wieder deutlich, dass die Pfade unserer Entwicklungsumgebung entsprechen, in der wir die Website schreiben. Die Pfade sind teilweise fest verdratet und müssen bei Bedarf angepasst werden. Wichtig bei dem Pfad für das XML-Daten-File ist, dass er relativ zu document-to-html.xsl berechnet wird und nicht relativ zu dem File, in das der Index eingefügt werden soll.

In <xsl:template match="index" mode="insertindex"> wird der erste Teil verwendet, die Buchstabenleiste des Index' aufzubauen. Der Vorteil an dieser Vorgehensweise ist, dass nur die Buchstaben eingetragen werden, die im Index vorkommen.

Der Rest ist eigentlich recht unkompliziert. Die Daten aus dem XML-Daten-File werden passend in die HTML-Tags eingefügt, damit die Darstellung den Wünschen entspricht.

Ich hoffe, dass die Beispiele eine gute Idee geben, wie man die Erstellung einer Website für den Autor gleichzeitig erleichtern und die Übersicht über die Daten gleichzeitig verbessern kann.

Viel Spaß beim Ausprobieren!

Markus Holzem, 11.03.2005
Websitegestaltung mit Apache Forrest
Markus Holzem
11.03.2005
website,gestaltung,forrest
Valid HTML 4.01!Valid CSS!Built with Apache Forrest