Wie ich meinem Linux-Rechner XML beigebracht habe

Dr. med. Claudia Neumann

08.01.2004

Zusammenfassung

Diese Artikel wurde geschrieben, um den Mitgliedern der -Mailingliste den Einstieg in XML für die Dokumentation mit DocBook zu erleichtern. Da es in dieser Mailingliste um Open Source-Software geht, sind diese Hinweise für Linux-Anwender gedacht.


Inhaltsverzeichnis

Was ist XML
XML schreiben mit der DocBook-DTD
Die Validierung
Die Transformation
Transformation nach HTML
Transformation nach PDF
Feedback

Was ist XML

Um in XML schreiben zu können, muß man trotz aller Hilfsmittel die Syntax von XML insbesondere mit DocBook kennen. Zu empfehlen sind folgende Webseiten:

XML schreiben mit der DocBook-DTD

Eine XML-Datei ist im Endeffekt eine Textdatei mit Mark-Ups, die bestimmten Regeln entsprechen, die durch eine DTD (Document Type Definition) festgelegt sind. Für XML mit DocBook brauchen wir die DTD von Docbook. Ich habe mir die neuste docbook-xml-Version 4.2 (Debian oder RPM-Paket) installiert. Unter den installierten Dateien ist besonders das Verzeichnis /usr/share/sgml/docbook/dtd/xml/4.2 interessant. In diesem Verzeichnis befindet sich die Datei docbookx.dtd, die mit den übrigen Dateien in diesem Verzeichnis die Regeln für Docbook-XML enthält.

Theoretisch könnten Sie in jedem Texteditor eine Datei mit DocBook-XML-Syntax erstellen und immer nachgucken, ob die Syntax richtig ist. Es gibt aber natürlich einige Hilfsmittel: es soll mit Kate funktionieren, mit OpenOffice soll es auch funktionieren. Ich habe mir Xemacs eingerichtet und es funktioniert.

Man installiere sich Xemacs. In SuSE kann man Xemacs-21.4.4, Xemacs-el-21.4.4. und Xemacs-info-21.4.4 installieren, in Debian benötigt man xemacs21, xemacs21-basesupport, xemacs21-bin, xemacs21-nomule und xemacs-support. Für die XML-Unterstützung müssen folgende Konfigurationen in $HOME/.xemacs erstellt werden:

Die Datei custom.el für SuSE:

(custom-set-variables
 '(recent-files-permanent-submenu t)
 '(browse-url-browser-function (quote browse-url-w3))
 '(bar-cursor nil)
 '(pending-delete-mode t nil (pending-del))
 '(truncate-lines t)
 '(line-number-mode t)
 '(kill-whole-line t)
 '(modeline-scrolling-method (quote scrollbar)))
(custom-set-faces
 '(default ((t (:size "9pt" :family nil))) t))

(setq minibuffer-max-depth nil)

für Debian:

(custom-set-variables
 '(recent-files-permanent-submenu t)
 '(gnuserv-program (concat exec-directory "/gnuserv"))
 '(browse-url-browser-function (quote browse-url-w3))
 '(bar-cursor nil)
 '(pending-delete-mode t nil (pending-del))
 '(truncate-lines t)
 '(line-number-mode t)
 '(kill-whole-line t)
 '(font-lock-mode t nil (font-lock))
 '(modeline-scrolling-method (quote scrollbar)))
(custom-set-faces
 '(default ((t (:size "12pt" :family nil))) t))

(setq minibuffer-max-depth nil)

Die Datei init.el:

;einige allgemeine Tastatur-Befehle
(global-set-key "\eg" 'goto-line)  ; M-g prompts for line number to enter
(global-set-key "\ei" 'overwrite-mode)  ; Schaltet zwischen Überschreiben und Einfügen hin und her.
(defalias 'xml-comment
  (read-kbd-macro "<!- - SPC - - > 4*<left>"))
(global-set-key "^Co" 'xml-comment)

; PSGML
(autoload 'xml-mode   "psgml"  "Major mode to edit XML files." t)
(autoload 'sgml-mode  "psgml"  "Major mode to edit SGML files." t)

; fuer welche Dateiendungen ?
(setq auto-mode-alist
    (append
	(list
	    '("\\.xml$" . xml-mode)
	    '("\\.html$" . html-mode)
	    '("\\.sgml$" . xml-mode)
	    '("\\.sgm$"  . xml-mode)
	    )
	auto-mode-alist))

; Validate command
(setq sgml-validate-command
    '("xmllint --valid --noout %s"))

(defadvice xml-mode (after run-xml-mode-hooks act)
       "Invoke `xml-mode-hook' hooks in the XML mode."
       (run-hooks 'xml-mode-hook))

;(autoload 'xsl-mode "xslide" "Major mode for XSL stylesheets." t)

;; Turn on font lock when in XSL mode
(add-hook 'xsl-mode-hook
	  'turn-on-font-lock)
	
(setq auto-mode-alist
    (append
	(list
	'("\\.fo" . xsl-mode)
	'("\\.xsl" . xsl-mode))
	auto-mode-alist))

; Create faces to assign to markup categories.
(make-face 'sgml-comment-face)
(make-face 'sgml-start-tag-face)
(make-face 'sgml-end-tag-face)
(make-face 'sgml-entity-face)
(make-face 'sgml-doctype-face)
    
; Assign attributes to faces.
(set-face-foreground 'sgml-comment-face "FireBrick")
(set-face-foreground 'sgml-start-tag-face "SlateBlue")
(set-face-foreground 'sgml-end-tag-face "SlateBlue")
(set-face-foreground 'sgml-entity-face "SlateBlue")
(set-face-foreground 'sgml-entity-face "Red")
(set-face-foreground 'sgml-doctype-face "FireBrick")
    
; Assign faces to markup categories.
(setq sgml-markup-faces
      '((comment . sgml-comment-face)
   	(start-tag . sgml-start-tag-face)
    	(end-tag . sgml-end-tag-face)
	(entity . sgml-entity-face)
	(doctype . sgml-doctype-face)))
    
; Tell PSGML to use the face settings.
(setq sgml-set-face t)
    
; Only allows valid elements to be inserted.
(setq sgml-omittag-transparent t)
    
; PSGML automatically inserts required elements.
(setq sgml-auto-insert-required-elements t)
    
; Einruecken einschalten
(setq sgml-indent-data t)

; weitere setq-Befehle
(setq sgml-balanced-tag-edit t)
(setq sgml-auto-insert-required-element t)
(setq sgml-set-face t)

Nun rufen Sie Xemacs auf. Wenn Sie jetzt eine Datei mit der Endung .xml laden, erscheinen in der Titelleiste weitere Items "SGML", "Modify", "Move", "Markup", "DTD". Die XML-Datei sollte am Anfang folgende Definitionen enthalten:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!--DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
                    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"-->
<!DOCTYPE article SYSTEM "/usr/share/sgml/docbook/dtd/xml/4.2/docbookx.dtd">

Für das richtige Highlighting muß eventuell in Debian unter "Options" -> "Syntax Highlighting" -> "In this Buffer" angeschaltet werden.

Entsprechend der XML-Definition wird mit der ersten Zeile angezeigt, daß es sich um ein XML-Dokument handelt. Mit den nächsten Zeilen wird die zugehörige DTD angegeben: 2. und 3. Zeile die Internet-Adresse der DTD, im Beispiel auskommentiert, da ich das Dokument auf meinem Rechner editiere und nicht dauernd über das Internet die DTD nachladen möchte. Diese Zeilen sind dafür gedacht, daß vielleicht in Zukunft die Webbrowser XML verstehen und zu einem XML-Dokument automatisch die entsprechende DTD dazuladen und alles zusammen anzeigen. Zur Zeit funktioniert das noch nicht. Die 4. Zeile ist der Link zu der entsprechenden DTD auf dem lokalen Rechner und muß je nach Datei-Architektur angepaßt werden.

Wenn man soweit ist, kann man auf "Move" -> "Next trouble spot" gehen. Xemacs lädt dann die angegebene DTD und highlighted die Tags. Leider stoppt dieser Prozeß bei SuSE häufig an den &-Zeichen, obwohl sie in der DTD definiert sind. Warum, habe ich noch nicht herausgefunden. Dies beeinträchtigt die weitere Bearbeitung jedoch nicht.

Man kann jetzt mit dem Editieren beginnen, indem man auf die nächste Zeile geht, dort rechts klickt und im Kontextmenü sämtliche an dieser Stelle möglichen Tags angezeigt bekommt. Auf den entsprechenden Tag klicken und es wird Anfang- und End-Tag des jeweiligen Tags sowie mögliche innere Tags eingefügt. Natürlich kann man auch Tags schreibend einfügen. Sie verändern ihre Farbe sobald Xemacs erkennt, daß es sich um einen Tag handelt. Abspeichern nicht vergessen.

Die Validierung

Man mag sich sehr gut mit XML auskennen, trotzdem ist ein XML-Dokument kein XML-Dokument, wenn man es nicht validiert hat. Das standardmäßig mit Xemacs installierte Validierungsprogramm nsgml ergab bei mir trotz richtiger Syntax alle möglichen Fehlermeldungen, sodaß ich jetzt xmllint aus dem libxml2-[utils]-Paket einsetze. Man kann theoretisch den Validierungsbefehl in der init.el eingeben. Leider wurde trotzdem bei SuSE und auch bei Debian der Befehl von einem internen Befehl überschrieben. Also muß man bei SuSE 8.2 in der Datei /usr/share/xemacs/xemacs-packages/lisp/psgml/auto-autoloads.el den nsgml-Befehl mit den Befehl

xmllint --valid --noout %s

ersetzte, bei Debian ist es die Datei /usr/share/xemacs21/packages/lisp/psgml/psgml.elc. Jetzt kann man im laufenden Xemacs-XML die Validierung durchführen und direkt die Fehler editieren.

Die Transformation

Transformation nach HTML

Wir können aus der validierten XML-Datei durch Transformation mit Hilfe der DocBook-XSL-Stylesheets verschiedenste Formate erstellen. Für die Transformation kann man bei SuSE Saxon-6.5 installieren, bei Debian lib-saxon-java. Java muß ebenfalls installiert sein. Als DocBook-XSL-Stylesheets kann man die neuste Version unter docbook-xsl-x.xx.tar.gz heruntergeladen (ich habe Version 1.61.2) und im Verzeichnis /usr/share/sgml/docbook eingerichtet oder man installiert in Debian das Paket docbook-xsl-1.60.1-1. Man muß jetzt Saxon mitteilen, welches Stylesheet man zur Umwandlung einsetzen möchte. Dadurch legt man fest, welches Format am Ende herauskommt. Für die HTML-Transformation habe ich mir zwei Scripten angelegt.

Das erste Skript gibt die HTML-Datei als einen einzigen File mit SuSE und docbook-xsl-1.61.2 aus:

#!/bin/bash
# Programm zum automatischen Starten von Saxon zur Umwandlung einer XML-Datei in eine große HTML-Datei

export CLASSPATH=/usr/lib/saxon/saxon.jar:/usr/lib/saxon/saxon-jdom.jar:/usr/lib/saxon/saxon-fop.jar
java com.icl.saxon.StyleSheet $1.xml /usr/share/sgml/docbook/docbook-xsl-1.61.2/html/docbook.xsl > $1.html

bei Debian sieht die Datei folgendermaßen aus:

#!/bin/bash
# Programm zum automatischen Starten von saxon zur Umwandlung von XML-Dateien nach HTML-Dateien

export CLASSPATH=/usr/share/java/saxon.jar:/usr/share/java/saxon-jdom.jar:/usr/share/java/saxon-fop.jar
java com.icl.saxon.StyleSheet $1.xml /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/docbook.xsl > $1.html

Der Pfad zu den Saxon-Dateien und zur Docbook-Stylesheet-Datei muß Ihrer Distribution entsprechend angepaßt werden.

Das zweite Script legt für jedes Kapitel eine neue HTML-Datei an, besonders empfehlenswert für "book"-XML ebenfalls für SuSE und docbook-xsl-1.61.2:

#!/bin/bash
# Programm zum automatischen Starten von saxon zur Umwandlung einer XML-Datei in mehrere HTML-Dateien
cp $1.xml html/$1.xml
cd html
export CLASSPATH=/usr/lib/saxon/saxon.jar:/usr/lib/saxon/saxon-jdom.jar:/usr/lib/saxon/saxon-fop.jar
java com.icl.saxon.StyleSheet $1.xml /usr/share/sgml/docbook/docbook-xsl-1.61.2/html/chunk.xsl 

Das Skript schreibt die Dateien in ein Unterverzeichnis /html, was vorhanden sein muß.

Für Debian sieht diese Datei folgendermaßen aus:

#!/bin/bash
# Programm zum automatischen Starten von saxon zur Umwandlung einer XML-Datei in mehrere HTML-Dateien
cp $1.xml html/$1.xml
cd html
export CLASSPATH=/usr/share/java/saxon.jar:/usr/share/java/saxon-jdom.jar:/usr/share/jave/saxon-fop.jar
java com.icl.saxon.StyleSheet $1.xml /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/chunk.xsl 

Transformation nach PDF

An der PDF-Transformation habe ich mir lange Zeit die Zähne ausgebissen, will es hier aber trotzdem verraten. Neben Saxon benötigen wir für diese Transformation auch noch FOP, downloadbar von xml.apache.org. Ich habe fop-0.20.4-bin.tar.gz ausgepackt und in /usr/lib/fop-0.20.4 installiert. Für die Konfiguration von FOP brauchen wir nun ein paar schöne TrueType-Fonts, wie sie jeder auf seinem Rechner herumliegen hat. Ich habe diese herumliegenden Fonts, die ja nicht mehr verwendet werden, da das dazugehörige Betriebssystem mit dem Anfangsbuchstaben "W" nicht mehr gestartet wird, in das Verzeichnis /usr/X11R6/lib/X11/fonts/truetype transferiert.

Mit dem Befehl

ls -l | awk '{ print $1 }' > test

erstellt man eine Datei "test", die die zu verwendenden Fonts enthält. Mit dem Skript im Verzeichnis /usr/lib/fop-0.20.4

#!/bin/bash
for file in $(grep ttf test)
do 
java -cp build/fop.jar:lib/xercesImpl-2.0.1.jar:lib/xml-apis.jar:lib/xalan-2.3.1.jar:lib/batik.jar org.apache.fop.fonts.apps.TTFReader /usr/X11R6/lib/X11/fonts/truetype/$file ../fop-0.20.4/conf/$file.xml
done

werden die Fonts ins XML-Format umgewandelt und entsprechende Dateien im Verzeichnis /usr/lib/fop-0.20.4/conf/ abgelegt. Die Datei userconfig.xml muß noch geändert werden:

<!DOCTYPE configuration SYSTEM "/usr/lib/fop-0.20.4/conf/config.dtd">
<!-- p/
     this file contains templates which allow an user easy 
     configuration of Fop. Actually normally you don't need this configuration 
     file, but if you need to change configuration, you should
     always use this file and *not* config.xml. 
     Usage: java org.apache.fop.apps.Fop -c userconfig.xml -fo fo-file -pdf pdf-file
-->


<configuration>

<!--  NOT IMPLEMENTED
basedir: normally the base directory is the directory where the fo file is 
         located. if you want to specify your own, uncomment this entry
-->
<!-- 
  <entry>
    <key>baseDir</key>
    <value></value>
  </entry>
-->

<!--
************************************************************************
                        HYPHENATION 
************************************************************************
-->
  
<!--
   hyphenation directory 
   if you want to specify your own directory with hyphenation pattern
   then uncomment the next entry and add the directory name
-->

<!--
  <entry>
    <key>hyphenation-dir</key>
    <value>/usr/src/fop-0.20.4/hyph</value>
  </entry>
-->

<!--
************************************************************************
  Add fonts here
************************************************************************
-->
<fonts>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/arial.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/arial.tff">
    <font-triplet name="Arial" style="normal" weight="normal"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/arialbd.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/arialbd.tff">
    <font-triplet name="Arial" style="normal" weight="bold"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/arialbi.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/arialbi.tff">
    <font-triplet name="Arial" style="italic" weight="bold"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/ariali.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/ariali.tff">
    <font-triplet name="Arial" style="italic" weight="normal"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/cour.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/cour.tff">
    <font-triplet name="Courier" style="normal" weight="normal"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/courbd.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/courbd.tff">
    <font-triplet name="Courier" style="normal" weight="bold"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/courbi.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/courbi.tff">
    <font-triplet name="Courier" style="italic" weight="bold"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/couri.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/couri.tff">
    <font-triplet name="Courier" style="italic" weight="normal"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/times.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/times.tff">
    <font-triplet name="Times New Roman" style="normal" weight="normal"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/timesbd.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/timesbd.tff">
    <font-triplet name="Times New Roman" style="normal" weight="bold"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/timesbi.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/timesbi.tff">
    <font-triplet name="Times New Roman" style="italic" weight="bold"/>
 </font>
 <font metrics-file="/usr/lib/fop-0.20.4/conf/timesi.xml" kerning="yes" embed-file="/usr/X11R6/lib/X11/fonts/truetype/timesi.tff">
    <font-triplet name="Times New Roman" style="italic" weight="normal"/>
 </font>
</fonts>
</configuration>

Bitte passen Sie das obige Skript ihren Pfaden und Fonts an.

Jetzt sind wir fast soweit, die PDF-Transformation zu beginnen. Ein kleines Skript hilft uns wieder:

#!/bin/bash
# Programm zum automatischen Starten von saxon zur Umwandlung von XML-Dateien nach PDF-Dateien
export JAVA_HOME=/usr/lib/j2se/1.3/jre
export FOP=/usr/lib/fop-0.20.4
export SAXON=/usr/lib/saxon
export CLASSPATH=$SAXON/saxon.jar:$SAXON/saxon-jdom.jar:$SAXON/saxon-fop.jar:$FOP/build/fop.jar:$FOP/lib/avalon-framework-cvs-20020315.jar:$FOP/lib/batik.jar:$FOP/lib/xalan-2.3.1.jar:$FOP/lib/xerxesImpl-2.0.1.jar:$FOP/lib/xml-apis.jar
java  com.icl.saxon.StyleSheet $1.xml /usr/share/sgml/docbook/docbook-xsl-1.61.2/fo/docbook.xsl > pdf/$1.fo
fop -d -c /usr/lib/fop/conf/userconfig.xml -fo pdf/$1.fo -pdf pdf/$1.pdf

In einem ersten Schritt wandelt Saxon die XML-Datei in eine FO-Datei um, im zweiten Schritt folgt die Transformation von FO nach PDF durch FOP. Es laufen dabei unheimlich viele Fehlermeldungen über den Bildschirm, besonders viele mit "not implemented yet". Aber meist läuft es durch und produziert eine PDF-Datei.

Wenn Sie sich dann die PDF-Datei anschauen, stellen Sie fest, das # anstelle des Trennzeichens eingesetzt wurde. In der Version 1.61.2 war der Trennstrich für Deutsch nicht eingerichtet. Es müssen folgende Zeilen in der Datei /usr/share/sgml/docbook/docbook-xsl-1.61.2/common/de.xml nach Zeile 169 eingefügt werden:

<l:gentext key="hyphenation-character" text="-"/>
   <l:gentext key="hyphenation-push-character-count" text="2"/>
   <l:gentext key="hyphenation-remain-character-count" text="2"/>

Nun wird der Trennstrich richtig angezeigt.

Ein weiteres Problem ergibt sich, wenn man Bilder in der PDF-Datei einbauen will. FOP kann Bilder nur im SVG-Format weiterverarbeiten. Wenn ich zum Beispiel den Doc-Pinguin in der APWiegand-in-Linux-Datei in PDF-Format anzeigen lassen will, ersetze ich folgendermaßen:

sed -e 's/<imagedata fileref="apwpinguin.png" format="PNG" align="right"\/>/<imagedata align="right" fileref="apwpinguin.svg" format="SVG"\/>/g' apw.xml > apwpdf.xml

Die SVG-Datei sieht dann folgendermaßen aus:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
     "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" >
<svg xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink" width="90px" height="100px">
<image xlink:href="apwpinguin.jpg" x="0" y="0" width="90px"
 height="100px"/> </svg>

Die apwpinguin.png-Datei habe ich mit Gimp nach jpg umgewandelt.

Feedback

Ich habe diesen kleinen Artikel weitgehend aus dem Gedächtnis geschrieben. Falls Konfigurationen, wie hier beschrieben, nicht funktionieren, bitte ich um kurze Rückmeldung, da ich dann wahrscheinlich noch weitere Konfigurationen vergessen habe. Bitte senden sie Hinweise oder Kommentare an mich oder die -Mailingliste.

Fragen zu den Programmen Saxon, FOP und DocBook senden Sie bitte an die jeweiligen Mailinglisten, da ich sicher kein Experte dieser Programme bin.