Archiv für Juni, 2010

Binärdateien mit Saxon schreiben

XSLT bietet von Haus aus keine Möglichkeit zur Ausgabe von Binärdateien wie Bildern. Aber zumindest Saxon-PE/Saxon-EE ab Version 9.2 bietet eine Erweiterung, um diese Beschränkung zu umgehen. Nach einigen Tests ist es mir gelungen, sowohl jpeg als auch png zu schreiben. Das Beispiel-Stylesheet hat folgenden Abschnitt:

<xsl:variable name="image" as="xs:hexBinary">89504E470D0A1A0A0000000D494844520000000D0000000F0403000000CD0D5844000000017352474200AECE1CE900000018504C544562129D80418A8851829E7972B09266DCD946F4FF39FEFFFC482C1765000000564944415408D725CD2B12C0200C04D030133C0A5D55DD2354A1A3D069A17BFF237403316FF217AC70190ABCD905A5E36ED4CE2FB18EA14F0E51AEB6B484AD6E0F6ED0A95643AB53B1EF94EEC2842517363912F3EBDF0F99462041E4FA77630000000049454E44AE426082</xsl:variable>
<xsl:result-document method="text" encoding="iso-8859-1" href="x.png" saxon:recognize-binary="yes">
	<xsl:processing-instruction name="hex" select="$image"/>
</xsl:result-document>

Ich hatte auf einem Mac mit <OxygenXML/> kein Glück bei der expliziten Angabe des Encodings, etwa hex.utf8, aber vielleicht habe ich nicht konsequent genug probiert.

Das vollständige Stylesheet steht unter http://www.expedimentum.org/example/xslt/binaerdaten-ausgabe.xsl zum Download bereit.

Nachtrag
Wenn man schon Erweiterungs-Funktionen bemüht, kann man die Arbeit auch gleich Java erledigen lassen. Damit ist man nicht mehr auf eine der »großen« Saxon-Versionen beschränkt; auch AltovaXML und Saxon-B 8.9 und 9.1 lassen sich zur Mitarbeit überreden. Ich habe zwei Varianten entwickelt: binaerdaten-ausgabe_java.xsl »borgt« sich nur den FileOutputStream von Java und wandelt den HexBinary-String per XSLT in eine Sequenz von Bytes um. binaerdaten-ausgabe_java_extern.xsl bedient sich der externen Klasse HexBinaryFileWriter, die die komplette Konvertierung und Ausgabe abwickelt. Die Erklärung folgt im nächsten Blog-Beitrag.

1 Kommentar

Include mehrerer Pattern in Schematron

Schematron bringt einen recht simplen Mechanismus zum Einbinden externen Schemata mit: das Element <sch:include/> bindet ein externes XML-Dokument ein, und zwar genau an der Stelle, wo <sch:include/> im Code steht. Das partielles Überschreiben oder gezielte Einbinden einzelner Pattern und Rules ist nicht möglich. Dies hat zwei Folgen:

  1. Da unterhalb von <sch:schema/> kein weiteres <sch:schema/> eingebunden werden darf, kann die eingebundene Datei nicht alleinstehend zum Validieren benutzt werden.
  2. Da <sch:pattern/> direkt unterhalb von <sch:schema/> stehen muss (es gibt in Schematron kein klammerndes Element wie etwa <define/> in RelaxNG), können mehrere Pattern nur eingebunden werden, wenn sie in der eingebundenen Datei als Wurzelelemente direkt nebeneinander stehen. Eine solche Datei ist aber kein wohlgeformtes XML, folgerichtig verweigert Schematron den Include.

Ein Thread auf der DSDL-Mailingliste und eine Anfrage auf der XML-DEV-Mailingliste ergaben zwar, dass das Problem bekannt ist, die vorgeschlagenen Lösungen sollen aber erst in zukünftigen Versionen von Schematron festgezurrt werden, und sie funktionieren jetzt noch nicht mit <OxygenXML/>. Deshalb entschied ich mich, auf die im grundlegenden XML-Standard definierte Einbindung externer Entities zurückzugreifen. Dieser Workaround sieht so aus:

Basis-Schematron:

<!DOCTYPE schema [
	<!ENTITY basic-pattern SYSTEM "basic-pattern.ent">
]>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
	&basic-pattern;
</schema>

eingebundene Entity-Datei (basic-pattern.ent):

<pattern xmlns="http://purl.oclc.org/dsdl/schematron">
	<!-- some rule -->
</pattern>
<pattern xmlns="http://purl.oclc.org/dsdl/schematron">
	<!-- some rule -->
</pattern>
<!-- add some more pattern here -->

Diese Datei ist kein wohlgeformtes XML, weil sie mehrere Wurzelelemente hat, sie wird aber nur eingebunden in andere Dateien verwendet – die dann wohlgeformt sind. In der Praxis wird man wohl einfach ein Schematron entwickeln und die Includes dann per Cut&Paste in die Entity-Datei verschieben, so dass die fehlende Wohlgeformtheit kein Nachteil ist.

erweitertes Schematron:

<!DOCTYPE schema [
	<!ENTITY basic-pattern SYSTEM "basic-pattern.ent">
]>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
	&basic-pattern;
	<!-- add some more pattern here -->
</schema>

Dieser Workaround hat verschiedene Vorteile:

  1. Externe Entity-Dateien sind konform zum XML- und Schematron-Standard.
  2. Die einbindenden Dateien lassen sich zusammen mit den eingebundenen Dateien validieren.
  3. Es sind keine Änderungen an etablierten Werkzeugen und Workflows notwendig (so ist es mir mit flüchtiger Recherche nicht gelungen, <OxygenXML/> andere Schematron-Stylesheets unterzuschieben).

Ich habe die drei Beispieldateien unter http://www.expedimentum.org/example/Schematron/ abgelegt.

Keine Kommentare