headerbild blog

Feature der Woche: XProc Filter

Ruft man sp --help auf, so erscheint folgender Eintrag:

$ sp --help
Usage: [parameter] command

--filter=FILTER          Run XPROC filter before publishing starts

Was hat es mit diesem Filter auf sich? Was ist XProc?

XProc ist eine in XML formulierte Sprache, um Anweisungen hintereinander auszuführen. Man kann es sich wie ein »in XML formuliertes Make« vorstellen, um verschiedene Dinge zu tun. So könnte man eine XSLT-Transformation anstoßen, XML validieren oder Dateien kopieren.

Eine XSLT-Transformation könnte so aussehen:

<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
    xmlns:c="http://www.w3.org/ns/xproc-step" version="1.0">
    <p:xslt name="Transformation">
        <p:input port="parameters">
            <p:empty/>
        </p:input>
        <p:input port="source">
            <p:document href="eingabedatei.xml"/>
        </p:input>
        <p:input port="stylesheet">
            <p:document href="transformation.xsl"/>
        </p:input>
    </p:xslt>
    <p:store href="data.xml"/>
</p:declare-step>

Diese Instruktionen speichert man z.B. unter filter.xpl.

Die Syntax ist zwar etwas gewöhnungsbedürftig, aber durchaus erlernbar. Der Wikipediaeintrag zu XProc hilft hier weiter

Nun kann man mit

sp --filter filter.xpl run

den Publisher starten, während vorher einmalig die XProc-Anweisungen ausgeführt werden.

Dieser Artikel bezieht sich auf den speedata Publisher in der Version 2.7.10. Andere Versionen haben womöglich andere Befehle oder die genannten Befehle zeigen ein anderes Verhalten. Bitte schau im Zweifelsfall in der Anleitung nach.

In der Serie »Feature der Woche« beschreibe ich einmal in der Woche mehr oder weniger nützliche Eigenschaften des Publishers. Kommentare gerne an mich per E-Mail oder einfach im Kommentarfeld.

von Patrick Gundlach |

Feature der Woche: Erstellen von QR-Codes

Das erste »Feature der Woche« im Jahr 2017 beschäftigt sich mit der Ausgabe von QR-Codes. Kürzlich sind mir GiroCodes über den Weg gelaufen. Das sind QR-Codes, die Rechnungsinformationen enthalten, mit denen man eine Online-Überweisung schnell und einfach durchführen kann.

Ein QR-Code, der Überweisungsinformationen enthält. Der Rahmen und der Text darüber sind nicht notwendig.

Der Befehl, um einen QR-Code zu erzeugen, lautet <Barcode>, z.B.:

<PlaceObject>
  <Barcode select="'Hallo Welt!'" type="QRCode" width="5"/>
</PlaceObject>

Hinweis: Es werden derzeit die Codes Code128, EAN13 und QRCode unterstützt. Sie werden intern erzeugt und benötigen keine Online-Verbindung.

In dem oben gezeigten Code sind die Überweisungsinformationen enthalten. Für das Beispiel nutze ich folgende Datendatei

<data>BCD
001
1
SCT
GENODEM1GLS
Greenpeace e.V.
DE49430609670000033401
EUR100.00


Meine Anschrift
</data>

Die einzelnen Felder nach dem Feld SCT sollten sich leicht erschließen. Es sind die BIC, Empfänger (UTF-8 kodiert), IBAN, Betrag, zwei Leerzeilen und der Verwendungszweck. Wichtig für die Kompatibilität mit dem GiroCode Standard ist, dass die Fehlerkorrektur im QR-Code auf »M« festgelegt ist. Seit der Version 2.7.10 kann man diese explizit festlegen.

So lautet die Ausgabe für den Code:

<Record element="data">
  <PlaceObject>
    <Barcode select="." type="QRCode" eclevel="M" width="4"/>
  </PlaceObject>
</Record>

Als Gimmick habe ich noch einen Rahmen um den Code gezeichnet mit dem Text darüber. Der Text ist in der Schriftart OpenSans Condensed und kann auf der Google Fonts Seite herunter geladen werden.

<Layout xmlns="urn:speedata.de:2009/publisher/en"
    xmlns:sd="urn:speedata:2009/publisher/functions/en">

    <LoadFontfile name="OpenSans-CondensedBold" filename="OpenSans-CondBold.ttf" />
    <DefineFontfamily name="girocode" fontsize="14" leading="14">
        <Regular fontface="OpenSans-CondensedBold"/>
    </DefineFontfamily>

    <Record element="data">
        <SetVariable variable="radius" select="'8pt'"/>
        <SetVariable variable="x" select="4"/>
        <SetVariable variable="y" select="3"/>
        <SetVariable variable="wd" select="4"/>
        <SetVariable variable="gap" select="$wd div 15"/>

        <PlaceObject row="{$y - $gap}" column="{$x - $gap}">
            <Frame framecolor="black"
                border-bottom-left-radius="{$radius}"
                border-bottom-right-radius="{$radius}"
                border-top-left-radius="{$radius}"
                border-top-right-radius="{$radius}"
                rulewidth="2pt">
                <Box width="{$wd + 2 * $gap}" height="{$wd + 2 * $gap}"
                     backgroundcolor="white"/>
            </Frame>
        </PlaceObject>

        <PlaceObject row="{$y - 3 * $gap}" column="{$x}">
            <Textblock width="{$wd}" textformat="centered" fontface="girocode">
                <Paragraph>
                    <Color name="#000066"><Value>GIRO</Value></Color>
                    <Color name="#FF000A"><Value>CODE</Value></Color>
                </Paragraph>
            </Textblock>
        </PlaceObject>


        <PlaceObject column="{$x}" row="{$y}" allocate="no">
            <Barcode select="." type="QRCode" eclevel="M" width="{$wd}"/>
        </PlaceObject>

    </Record>
</Layout>

Die Idee ist, erst eine leere Box zu zeichnen mit dem abgerundeten Rahmen. Die Box muss etwas größer sein, als der eigentliche Code. Anschließend wird der Text GIROCODE geschrieben und zum Schluss der eigentliche QR-Code eingepasst. Mit den Variablen kann man die Größe und Position leicht anpassen. Das Ergebnis ist im Bild oben zu sehen.

Viel Spaß beim Spenden.

Dieser Artikel bezieht sich auf den speedata Publisher in der Version 2.7.10. Andere Versionen haben womöglich andere Befehle oder die genannten Befehle zeigen ein anderes Verhalten. Bitte schau im Zweifelsfall in der Anleitung nach.

In der Serie »Feature der Woche« beschreibe ich einmal in der Woche mehr oder weniger nützliche Eigenschaften des Publishers. Kommentare gerne an mich per E-Mail oder einfach im Kommentarfeld.

von Patrick Gundlach |

Frohe Weihnachten

Ich mache ein paar Tage Pause und wünsche euch ein paar geruhsame freie Tage. Pause mache ich nicht wirklich, sondern arbeite an einer kleinen Überraschung, die hoffentlich Anfang Februar fertig sein wird.

Ansonsten möchte ich noch darauf hinweisen, dass es noch ein Ticket für die XML-Konferenz im Februar gibt.

Das nächste »Feature der Woche« gibt es voraussichtlich am 9. Januar 2017.

von Patrick Gundlach |

XML-Konferenz in Prag

Wie jedes Jahr findet auch 2017 die XML-Konferenz in Prag statt. Siehe

http://www.xmlprague.cz/

Für uns eine Neuerung: dieses Jahr sind wir Sponsor der Konferenz (genauer: wir sponsern das Bier auf dem Social Evening 🍻). Und wir haben noch eine Eintrittskarte (full pass) zu vergeben. Wer die Karte haben möchte, möge sich melden, entweder per E-Mail oder per Kommentar hier (oder per Twitter).

von Patrick Gundlach |

Feature der Woche: Griffmarken

Dies ist eigentlich kein Feature des Publishers, aber trotzdem ein nettes Gimmick, das man dank der Programmiermöglichkeiten des Publishers erzeugen kann.

Was sind Griffmarken?

Griffmarken sind Markierungen an der Außenkante eines Katalogs oder eines Nachschlagewerks, die das aktuelle Kapitel anzeigen.

Griffmarken im Telefonbuch (huch!)

Weniger aufdringlich, trotzdem praktisch

Eine Eigenschaft der Griffmarke ist, dass sie über den rechten Rand bzw. über den linken Rand des Papiers hinaus geht. Das heißt, die Schnittkante der Griffmarke ist im farbigen Bereich, so dass die Farbe auch im zugeklappten Zustand zu erkennen ist.

Umsetzung im Publisher

An Griffmarken ist natürlich nichts besonders, sie sind entweder Boxen oder Linien in einer bestimmten Farbe. Hier folgt ein Beispiel für Kapitelnummern in einer quadratischen Box. Der Anschnitt ist auf 3mm festgelegt. Etwas Magie kommt ins Spiel, wenn ich weiß, wo die Griffmarken sind. Hier sind sie am rechten Rand und sie sollen natürlich in den Anschnitt mit hinein ragen. Dafür ist bei dem Befehl Box der Parameter bleed="right" gesetzt. Hiermit erstreckt sich die Box um die Beschnittzugabe nach rechts. (Das ist natürlich direkt am Rand sinnvoll.)

Im Beispiel wird die Kapitelnummer in der Variablen kapitel gespeichert und in einer Schleife ausgegeben. Im »echten Leben« würde man das natürlich in den Seitentyp (AtPageShipout) einfügen und immer nur eine Griffmarke ausgeben.

<Layout
    xmlns="urn:speedata.de:2009/publisher/en"
    xmlns:sd="urn:speedata:2009/publisher/functions/en">

    <Options bleed="3mm"/>

    <DefineFontfamily name="Griffmarke" fontsize="15" leading="15">
        <Regular fontface="TeXGyreHeros-Bold"/>
    </DefineFontfamily>

    <Record element="data">
        <Loop select="4" variable="kapitel">
            <PlaceObject column="200mm" row="{20 + 20 * $kapitel}mm">
                <Box width="1cm" height="1cm" backgroundcolor="black" bleed="right"/>
            </PlaceObject>
            <PlaceObject column="200mm" row="{20 + 20 * $kapitel}mm">
                <Table width="1cm" stretch="max">
                    <Tr valign="middle" minheight="1">
                        <Td align="center">
                            <Paragraph fontface="Griffmarke" color="white">
                                <Value select="$kapitel"/>
                            </Paragraph>
                        </Td>
                    </Tr>
                </Table>
            </PlaceObject>
        </Loop>
    </Record>
</Layout>

Die grüne Linie zeigt das Endformat, die blaue Linie die Außenkante des unbeschnittenen Papiers

Dieser Artikel bezieht sich auf den speedata Publisher in der Version 2.7.9. Andere Versionen haben womöglich andere Befehle oder die genannten Befehle zeigen ein anderes Verhalten. Bitte schau im Zweifelsfall in der Anleitung nach.

In der Serie »Feature der Woche« beschreibe ich einmal in der Woche mehr oder weniger nützliche Eigenschaften des Publishers. Kommentare gerne an mich per E-Mail oder einfach im Kommentarfeld.

von Patrick Gundlach |

Feature der Woche: Gruppen (Group)

Eine der bedeutendsten Eigenschaften des Publishers ist die Möglichkeit, Objekte auf einer virtuellen Seite (Group) zu platzieren, um sie anschließend auszumessen bzw. zusammenhängend zu platzieren. Diese virtuelle Seite hat erst einmal keine Breite und keine Höhe. Die Fläche passt sich den Ausmaßen dem Inhalt an. Somit lassen sich Fragen beantworten wie »Passt der Artikel (mit Bild und Beschreibung) noch auf die Seite?« oder »Wie sehr muss ich die Schriftgröße verkleinern, damit der ganze Text auf eine A4-Seite passt?«.

Ebenfalls ist es möglich, diese virtuelle Seite mit einem eigenen Seitenraster zu versehen. Damit lassen sich zum Beispiel Objekte auf der virtuellen Seite feiner positionieren, als es mit einem gröberen Seitenraster der Hauptseite möglich ist.

Einige Dinge muss man aber beachten, wenn man die Gruppen einsetzt:

  • Die Breitenangaben bei Textblöcken und Tabellen sind nun obligatorisch, da es kein »natürliches Maximum« gibt.
  • Die Seitenraster können nicht mit nx und ny bestimmt werden, sondern nur mit festen Werten für Höhe und Breite.
  • Bereiche können mit Gruppen nicht kombiniert werden. D.h. bei PlaceObject und ähnlichen Befehlen darf area nicht angegeben werden.
  • Platzierungen in Gruppen dürfen nicht absolut (z.B. row="2mm") erfolgen.

Wie werden Gruppen benutzt?

<Layout
    xmlns="urn:speedata.de:2009/publisher/en"
    xmlns:sd="urn:speedata:2009/publisher/functions/en">

    <Trace grid="yes" objects="yes"/>

    <Record element="data">
        <Group name="test">
            <Contents>
                <PlaceObject row="2" column="2">
                    <Image width="3" file="_sampleb.pdf"/>
                </PlaceObject>
            </Contents>
        </Group>
        <PlaceObject groupname="test"/>
    </Record>
</Layout>

Die Gruppe nimmt den minimalen Platz in Anspruch.

Ist die Gruppe erzeugt, aber noch nicht platziert, dann kann ich mit bestimmten XPath-Funktionen die Maße der Gruppe ausmessen: sd:group-width('gruppenname') und sd:group-height('gruppenname') geben die Breite in und Höhe in ganzen Rasterzellen aus. Im Beispiel ergibt

<Message select="sd:group-height('test')"/>

die Zahl 6 in der Ausgabe, obwohl die Gruppe nur die Höhe von ca. 5,2 Zellen hat. Der Publisher rechnet im Prinzip immer mit ganzen Rasterzellen.


Damit ist eigentlich schon alles gesagt, was zum Thema Gruppen gehört. Die Anwendungsfälle sind sehr vielfältig. Im Prinzip geht es hier immer um die Frage: wie groß sind diese Objekte? Passen sie noch auf die Seite? Muss ich hier einen Umbruch einfügen? Und so fort. Am besten spielt man ein wenig mit den virtuellen Seiten, um sich damit vertraut zu machen. Richtig benutzt sind sie ein mächtiges Werkzeug.

Dieser Artikel bezieht sich auf den speedata Publisher in der Version 2.7.9. Andere Versionen haben womöglich andere Befehle oder die genannten Befehle zeigen ein anderes Verhalten. Bitte schau im Zweifelsfall in der Anleitung nach.

In der Serie »Feature der Woche« beschreibe ich einmal in der Woche mehr oder weniger nützliche Eigenschaften des Publishers. Kommentare gerne an mich per E-Mail oder einfach im Kommentarfeld.

von Patrick Gundlach |

Feature der Woche: Platzierung von Objekten

Objekte werden immer entweder innerhalb des Rasters platziert oder mit absoluten Maßen. Beide Möglichkeiten haben ihre Vorteile und Nachteile und lassen sich nicht mischen. Der Befehl, um Objekte zu platzieren, heißt PlaceObject. Die Reihenfolge der Objektplatzierungen ist wichtig. Einerseits gibt es bei der Platzierung im Raster einen virtuellen Cursor, der sich die Position des letzten Objekts merkt. Andererseits werden später ausgegebene Objekte über die vorherigen Objekte gelegt.

von Patrick Gundlach |

Feature der Woche: Zwischensummen in Tabellen

Manchmal möchte man in Tabellen in Kopf- bzw. Fußzeilen eine Zwischensumme bzw. Übertrag (engl. etwa »running sum«) ausgeben. Hier ist das Problem, dass das eine dynamische Information ist, die sich aus dem zur Verfügung stehenden Platz ergibt. Ist die Seite kürzer, so ist die Summe eine andere. Das heißt, dass man die Zahl nicht im Vorfeld als Kopf- oder Fußzeile definieren kann.

von Patrick Gundlach |

Feature der Woche: Hintergrund in Tabellen

Nachdem letzte Woche Funkstille war (fast, zumindest gab es keinen Beitrag in der Reihe »Feature der Woche«), ist diese Woche das Thema »Hintergrund in Tabellen« dran.

Einfärben von Zellen

Man einzelne Zellen oder Zeilen einfärben. Dazu gibt es sowohl bei Tr als auch bei Td das Attribut backgroundcolor vorhanden:

von Patrick Gundlach |