Inżynieria biomedyczna Projekt Przygotowanie i realizacja kierunku inżynieria biomedyczna studia międzywydziałowe współfinansowany ze środków Unii Europejskiej w ramach Europejskiego Funduszu Społecznego.
Ø Formatowanie dokumentów XSL:FO wykład 11 Kontakt: Jacek Rumiński Katedra Inżynierii Biomedycznej, pk. 106, tel.: 3472678, fax: 3471757, e-mail: jwr@eti.pg.gda.pl Projekt Przygotowanie i realizacja kierunku inżynieria biomedyczna studia międzywydziałowe współfinansowany ze środków Unii Europejskiej w ramach Europejskiego Funduszu Społecznego.
Istotną częścią specyfikacji XSL jest definiowanie obiektów formatujących (FormaRng Objects). Obiekty formatujące stanowią treść rozdziału 6 specyfikacji XSL 1.0. Umożliwiają odwzorowanie z formatu składowania danych na format prezentacji danych (w układzie składu tekstu). Specyfikacja określa zarówno składnię wykorzystania obiektów formatujących jak i ich pełny zestaw. Wykorzystywana przestrzeń nazw dla FO to: xmlns:fo="h\p:// www.w3.org/1999/xsl/format". Zastosowanie takiego opisu transformacji danych (XML) umożliwia generację (za pomocą odpowiedniego oprogramowania) docelowego dokumentu prezentacji danych, np. PDF. 3
Dokument formatujący XSL- FO jest dokumentem XML, a zarazem dokumentem XSL. Zawiera specjalne znaczniki, służące do ułożenia treści informacji na stronie o określonym (definiowanym) formacie. Ogólna postać pliku XSL- FO może wyglądać następująco: <?xml version="1.0" encoding="ue- 8"?> <fo:root xmlns:fo="hlp://www.w3.org/1999/xsl/format"> <fo:layout- master- set> <fo:simple- page- master master- name="a4"> <! Tu dane szablonu strony - - > </fo:simple- page- master> </fo:layout- master- set> <fo:page- sequence master- reference="a4"> <! Tu treść strony - - > </fo:page- sequence> </fo:root> 4
Opis prezentacji zaczyna się od obiektu formatującego <fo:layout- master- set>, który zawiera jeden lub więcej elementów typu page master lub page sequence master określających układ dokumentu, np. (in od inch - cale): <fo:simple- page- master master- name="all" page- height="297mm" page- width="210mm" margin- top="1in" margin- bolom="1in" margin- le_="0.5in" margin- right="0.5in"> <fo:region- body region- name="plan" margin- top="10in" margin- bolom="0in" margin- le_="4in" margin- right="0in"/> </fo:simple- page- master> 5
Formatowanie z XSL- FO umożliwia określenie prostokątnych bloków, w których będzie zawarta treść informacji (stała lub pobrana z dokumentu XML). Do podstawowych bloków zaliczamy: - strony, zawierające: - regiony, zawierające: - bloki, zawierające inne bloki lub: - wiersze (linie), zawierające: - fragmenty wierszy (inline). Wszelkie wymiarowanie układu bloków odbywa się z użyciem absolutnych lub względnych jednostek: cm - centymetr; mm - milimetr; in - cal=2.54cm pt - punkt = 1/72in, 1/72cala; pc pica=12pt; px - piksele (rozmiar zależy od ekranu); em (jednostka względna) określa bieżący rozmiar czcionki, np. 1.2em to rozmiar o 0.2 większy niż bieżący. 6
Odwzorowywanie oraz wprowadzanie własnego tekstu odbywa się w obrębie elementu <fo:flow>. Wartość atrybutu tego elementu flow- name określa gdzie przetwarzane dane mają być zawarte. Uprośćmy na razie tak, że zawartość elementy <fo:flow> to po prostu tekstowy zbiór informacji, np. Tu bedzie plan zajec!. Tekst ten chcemy rozmieścić na stronie w obrębie jakiegoś bloku. W tym celu zapiszmy dokument XSL- FO: <?xml version="1.0" encoding="utf-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/xsl/ Format"> <fo:layout-master-set> <fo:simple-page-master master-name="all" page-height="297mm" page-width="210mm" margin-top="1in" margin-bottom="1in" margin-left="0.5in" margin-right="0.5in"> <fo:region-body region-name="plan" margintop="10in" margin-bottom="0in" margin-left="4in" margin-right="0in"/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="all"> <fo:flow flow-name="plan"> <fo:block> Tu bedzie plan zajec!</fo:block> </fo:flow> </fo:page-sequence> </fo:root> 7
Dokonajmy interpretacji powyższego zapisu: 1. najpierw dodajemy nagłówki xml i xsl 2. następnie główny układ stron, który nazywamy all 3. parametry układu strony to wymiar=a4 i marginesy w calach góra, dół 1 cal reszta 0,5 cala 4. na stronie definiujemy region o marginesach górny=10cali, lewy=4cale reszta 0, 5. region nazywamy plan 6. definiujemy element sekwencji stron (treści) w odniesieniu do układu stron (master- reference= all ) 7. w sekwencji stron umieszczamy element <fo:flow>, o nazwie, która pozwoli na odwzorowanie treści do regionu flow- name= plan, 8. element <fo:flow> definiuje blok, w którym będzie zawarty tekst, który to blok umieszczony zostanie w regionie na stronie. 8
Mając dokument XSL- FO (ze stałą wartością tekstu) pragniemy wygenerować docelową formę dokumentu, np. PDF. W tym celu musimy posłużyć się procesorem transformującym źródło do docelowego formatu. W przykładach z XSL wystarczyła przeglądarka. Teraz jednak chcemy uzyskać układ strony w PDF dlatego musimy posłużyć się procesorem FO, czyli specjalnie utworzony, programem przetwarzającym źródłowe dokumenty XSL- FO do danego formatu (np. PDF). W tym celu możemy posłużyć się licznymi programami komercyjnymi (np. Ecrion, XF Designer: render.exe - fo workplan.fo - pdf workplan.pdf lub analogicznie dla RenderX, XEP: h\p:// www.renderx.com/tools/xep.html) lub wykorzystać narzędzie darmowe Apache- FOP (które można pobrać ze strony h\p://xmlgraphics.apache.org/fop/download.html). Apache FOP dostarcza zarówno biblioteki programistyczne do transformacji dokumentów jaki skrypty uruchamiane z linii poleceń. 9
Po pobraniu Apache FOP wykonajmy następujące polecenie (używając fop.sh lub fop.bat, stosownie do systemu operacyjnego): fop workplan0.fo workplan.pdf W rezultacie (jeśli nie będzie błędów w budowie dokumentu.fo) otrzymamy wynik w postaci pliku PDF: 10
W celu zrozumienia znaczenia marginesów można przeprowadzić różne eksperymenty z wartościami marginesów i po wygenerowaniu PDF zobaczyć rezultaty. Przygotowując wydruk ważną rolę odgrywa rodzaj czcionki. W przypadku procesora Apache FOP można skonfigurować wczytywanie czcionek systemowych/własnych przez: edycję pliku konfiguracyjnego conf/fop.xconf dopisanie w nim linii: ( ) <renderers> <renderer mime="application/pdf"> <fonts> <directory>/users/jwr/desktop/fop-1.0/myfonts</directory> <auto-detect/> </fonts> ( ) uruchomienie skryptu z podaniem ścieżki do pliku konfiguracyjnego fop - c conf/fop.xconf workplan1.fo workplan1.pdf 11
<?xml version="1.0" encoding="utf-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/xsl/format"> <fo:layout-master-set> <fo:simple-page-master master-name="all" page-height="297mm" page-width="210mm" margin-top="1in" margin-bottom="1in" margin-left="0.5in" margin-right="0.5in"> <fo:region-body region-name="plan" margin-top="1in" margin-bottom="0in" margin-left="1in" margin-right="0in"/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="all"> <fo:flow flow-name="plan" font-family="georgia" font-size="40pt"> <fo:block> Tu będzie plan zajęć!</fo:block> </fo:flow> </fo:page-sequence> </fo:root> 12
Blok tekstu można formatować za pomocą szeregu atrybutów i elementów. Przykładowo atrybut border umożliwia dodanie ramki dookoła bloku, np. (czerwona ramka grubości 2 punktów): <fo:block text- align="jusafy" border="2pt solid red"> Tu będzie plan zajęć!</fo:block> Tworząc efekty graficzne można wykorzystać różnej formy ramki, obrazy, kolory, grafikę SVG, itp. Przykładowy, poniższy fragment ilustruje jak zaznaczyć pojedyncze słowo w wierszu tekstowym: <fo:block> Tu będzie plan <fo:inline background="green" border="3pt solid green"> zajęć </fo:inline> Jacka Rumińskiego</ fo:block>, co umożliwia wygenerowanie rezultatu pokazanego na rysunku 13
Formatowanie tekstu możliwe jest poprzez szereg własności dotyczących czcionek (np.: font- family, font- weight, font- style, font- size, font- variant) I położenia tekstu w ramach bloku (np.: text- align, text- align- last, text- indent, start- indent, end- indent, break- before, break- awer, reference- orientaron). Przykładowo układ strony typu landscape można uzyskać ustawiając własność strony reference- orientaron= 90 (np. atrybut elementu simple- page- master). Kolejny przykład demonstruje możliwość wykorzystania grafiki wektorowej definiowanej przez inny dialekt XML, czyli SVG. Obiekty SVG mogą być zanurzone w dokumencie XSL- FO (prostokąt wypełniony gradientem kolorów oraz tekst): 14
<?xml version="1.0" encoding="utf-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/xsl/format"> <fo:layout-master-set> <fo:simple-page-master master-name="all" page-height="297mm" page-width="210mm" margin-top="10mm" margin-bottom="10mm" margin-left="10mm" margin-right="10mm"> <fo:region-body region-name="plan" margin-top="0in" margin-bottom="0in" margin-left="1in" margin-right="0in"/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="all"> <fo:flow flow-name="plan" font-family="georgia" font-size="40pt"> <fo:block> <fo:instream-foreign-object content-height="200mm"> <svg xmlns="http://www.w3.org/2000/svg" width="150mm" height="200mm"> </fo:block> </fo:flow> </fo:page-sequence> </fo:root> <radialgradient id="grad" gradientunits="userspaceonuse" cx="60mm" cy="70mm" r="50mm" fx="60mm" y="70mm"> <stop stop-color="blue" offset="0"/> <stop stop-color="green" offset="0.4"/> <stop stop-color="yellow" offset="0.6"/> <stop stop-color="orange" offset="0.8"/> <stop stop-color="red" offset="1.0"/> </radialgradient> <rect x="10mm" y="20mm" width="100mm" height="100mm" fill="url(#grad)" stroke-width="1mm"/> <text font-family="georgia" font-size="36pt" x="10mm" y="130mm"> Przykład SVG! </text> </svg> </fo:instream-foreign-object> 15
16
Zanim przejdziemy do możliwości pobierania danych z dokumentu XML do XSL- FO rozważmy jeszcze problem sekwencji stron, czyli podziału tekstu na kolejne bloki. Sekwencję stron docelowego dokumentu uzyskuje się poprzez zastosowanie elementów <fo:page- sequence>. Każda strona odwołuje się do wzorca strony (page master), który określa układ danej strony. Treść strony końcowej ujęta jest w poznanym już elemencie <fo:flow>. Wypełniając docelową stronę tekstem (pobieranym z <fo:flow>) może się okazać, że tekst zajmie więcej niż jedną stronę wydruku. Wówczas utworzona zostanie kolejna strona (o tym samym układzie page master), później kolejna, aż do wydrukowania całego tekstu źródłowego. 17
Element <fo:flow> posiada atrybut flow- name. Atrybut ten może przyjąć jedną z predefiniowanych wartości: xsl- region- body (środek- ciało regionu), xsl- region- before (nagłówek), xsl- region- awer (stopka), xsl- region- start (lewa kolumna), xsl- region- end (prawa kolumna). 18
Blok (<fo:block>) posiada również wyróżnialne obszary otaczające ciało (treść) bloku, są to: space before oraz space awer czyli wolny obszar przed i po bloku margin margines wokół bloku border ramka bloku padding obszar pomiędzy ramką, a treścią bloku content treść bloku. Rozpatrzmy prosty przykład dodania bloku tekstu do ciała region: 19
<?xml version="1.0" encoding="utf-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/xsl/format"> <fo:layout-master-set> <fo:simple-page-master master-name="tytul" margin="10mm" page-height="297mm" pagewidth="210mm"> <fo:region-body margin="60mm"/> </fo:simple-page-master> <fo:page-sequence-master master-name="stronatytulowa"> <fo:single-page-master-reference master-reference="tytul"/> </fo:page-sequence-master> </fo:layout-master-set> <fo:page-sequence master-reference="stronatytulowa"> <fo:flow flow-name="xsl-region-body" font-family="georgia" font-size="30pt"> <fo:block text-align="center" text-indent="2mm" border="2pt solid red"> Raport z XML-FO. </fo:block> </fo:flow> </fo:page-sequence> </fo:root> 20
W układzie strony (layout- master) zdefiniowano prosty układ strony (simple- page- master) A4 wraz z regionem o marginesach z 4 stron równych 6cm. Następnie zdefiniowano drugi prosty układ strony odwołując się do pierwszego (reference= tytul ). Służy to wyłącznie celom demonstracyjnym. Dalej, zapisano sekwencję stron (page- sequence), od której żąda się zgodności z prostym układem strony o nazwie stronatytulowa (czyli tak naprawdę z układem tytul ). Po transformacji do PDF otrzymamy efekt ukazany na rysunku 21
Strony przygotowywanego dokumentu są grupowane w sekwencję stron. Prześledźmy teraz przykład, w który utworzono dodatkowy układ strony na treść dokumentu (czyli kolejne strony po stronie tytułowej) i zastosowano taki układ dla dużej ilości tekstu. Duża ilość wierszy tekstu spowoduje, że wygenerowana zostanie taka liczba stron, aby cały tekst był wykorzystany. Dodatkowo w poniższym przykładzie pokazano możliwość wykorzystania nagłówka (region- before) oraz stopki (region- awer), jak również numerowanie stron. 22
<?xml version="1.0" encoding="utf-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/xsl/format"> <fo:layout-master-set> <fo:simple-page-master master-name="tytul" margin="10mm" page-height="297mm" page-width="210mm"> <fo:region-body margin="60mm"/> </fo:simple-page-master> <fo:page-sequence-master master-name="stronatytulowa"> <fo:single-page-master-reference master-reference="tytul"/> </fo:page-sequence-master> <fo:simple-page-master master-name="tresc" margin="15mm" page-height="297mm" page-width="210mm"> <fo:region-body margin="15mm" /> <fo:region-before region-name="naglowek" extent="15mm" /> <fo:region-after region-name="stopka" extent="15mm" /> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="stronatytulowa"> <fo:flow flow-name="xsl-region-body" font-family="georgia" font-size="30pt"> <fo:block text-align="center" text-indent="2mm" border="2pt solid red"> Raport z XML-FO. </fo:block> </fo:flow> </fo:page-sequence> 23
<fo:page-sequence master-reference="tresc"> <fo:static-content flow-name="naglowek"> <fo:block border-bottom-width="thin" border-bottom-style="solid" border-bottom-color="blue" font-weight="bold" text-align="center"> Raport z XML-FO </fo:block> </fo:static-content> <fo:static-content flow-name="stopka"> <fo:block border-top-width="thin" border-top-style="solid" border-top-color="blue" font-weight="bold" text-align="center"> Jacek W. Ruminski, strona <fo:page-number/> </fo:block> </fo:static-content> <fo:flow flow-name="xsl-region-body" font-family="georgia" font-size="12pt"> <fo:block text-align="justify" text-indent="2mm" > Omawiając pojęcie reprezentacja informacji (i dużo więcej tekstu...) </fo:block> </fo:flow> </fo:page-sequence> </fo:root> 24
25
Tekst na kolejnych stronach można ciekawie układać np. w wielu kolumn. W tym celu wystarczy ustawić odpowiednie atrybuty dla elementu <fo:region- body>, np. dla poprzedniego przykładu: <fo:simple-page-master master-name="tresc" margin="15mm" page-height="297mm" pagewidth="210mm"> <fo:region-body margin="15mm" column-gap="10mm" column-count="2"/> <fo:region-before region-name="naglowek" extent="15mm" /> <fo:region-after region-name="stopka" extent="15mm" /> </fo:simple-page-master> Taki układ wygeneruje dwie kolumny tekstu z odstępem pomiędzy nimi wielkości 1cm. Pokazano to na rysunku 26
27
Ostatnim elementem, jaki zostanie tu omówiony będzie tabela. W celu wygenerowania w dokumencie docelowym tabeli można wykorzystać szereg elementów XSL- FO: fo:table- and- capron, fo:table, fo:table- capron, fo:table- column, fo:table- header, fo:table- footer, fo:table- body, fo:table- row, fo:table- cell. 28
<?xml version="1.0" encoding="u{- 8"?> <fo:root xmlns:fo="h\p://www.w3.org/1999/xsl/format"> <fo:layout- master- set> <fo:simple- page- master master- name="all" page- height="210mm" page- width="297mm" margin="10mm"> <fo:region- body region- name="plan" margin="5mm"/> </fo:simple- page- master> </fo:layout- master- set> <fo:page- sequence master- reference="all"> <fo:flow flow- name="plan" font- family="georgia" font- size="20pt"> <fo:table border- collapse="collapse" font- size="14pt" font- family="arial"> <fo:table- column column- width="20%" background- color="rgb(255,246,206)"/> <fo:table- column column- width="20%"/> <fo:table- column column- width="20%" background- color="rgb(255,246,206)"/> <fo:table- column column- width="20%"/> <fo:table- column column- width="20%" background- color="rgb(255,246,206)"/> <fo:table- header color="rgb(255,255,255)" background- color="rgb(125,73,2)" font- weight="bold"> <fo:table- row> <fo:block> Poniedziałek </fo:block> <fo:block> Wtorek</fo:block> <fo:block>środa </fo:block> <fo:block>czwartek</fo:block> <fo:block>piątek </fo:block> </fo:table- row> </fo:table- header> 29
<fo:table- body> <fo:table- row> <fo:block>plan dla poniedziałku </fo:block> <fo:block>plan dla wtorku</fo:block> <fo:block>plan dla środy</fo:block> <fo:block>plan dla czwartku</fo:block> <fo:block>plan dla piątku</fo:block> </fo:table- row> </fo:table- body> </fo:table> </fo:flow> </fo:page- sequence> </fo:root> 30
Ostatnią częścią omówienia XSL- FO będzie metoda powiązania informacji w dokumencie XML z arkuszem XSL- FO i wygenerowanie wyjściowego formatu prezentacji informacji. Połączenie XML z XSL- FO nie jest złożone, albowiem odbywa się to tak samo jak we wcześniejszych przykładach z XSLT (przecież XSL- FO to też XSL). Typowe zastosowanie: <xsl:template match="tu_xpath_do_xml"> <fo:block> //oczywiście tworząc odpowiednie formatowanie <xsl:apply- templates/> </fo:block> </xsl:template> 31
<?xml version="1.0" encoding="u{- 8"?> <xsl:stylesheet version="1.0" xmlns:xsl="h\p://www.w3.org/1999/xsl/transform"> <xsl:template match="/"> <fo:root xmlns:fo="h\p://www.w3.org/1999/xsl/format"> <fo:layout- master- set> <fo:simple- page- master master- name="all" page- height="210mm" page- width="297mm" margin="10mm"> <fo:region- body region- name="plan" margin="16mm"/> <fo:region- before region- name="naglowek" extent="15mm" /> </fo:simple- page- master> </fo:layout- master- set> <fo:page- sequence master- reference="all"> <fo:starc- content flow- name="naglowek"> <fo:block border- bo\om- width="thin" border- bo\om- style="solid" border- bo\om- color="blue" font- family="georgia" font- size="20pt" font- weight="bold" text- align="center"> PLAN ZAJĘĆ JACKA RUMIŃSKIEGO, ROK: <xsl:value- of select="workplan/@year"/> </fo:block> </fo:starc- content> <fo:flow flow- name="plan" font- family="georgia" font- size="20pt" 32
<fo:table border- collapse="collapse" font- size="14pt" font- family="arial"> <fo:table- column column- width="20%" background- color="rgb(255,246,206)"/> <fo:table- column column- width="20%"/> <fo:table- column column- width="20%" background- color="rgb(255,246,206)"/> <fo:table- column column- width="20%"/> <fo:table- column column- width="20%" background- color="rgb(255,246,206)"/> <fo:table- header color="rgb(255,255,255)" background- color="rgb(125,73,2)" font- weight="bold"> <fo:table- row> <fo:block> Poniedziałek </fo:block> <fo:block> Wtorek</fo:block> <fo:block>środa </fo:block> <fo:block>czwartek</fo:block> <fo:block>piątek </fo:block> </fo:table- row> </fo:table- header> 33
<fo:table- body> <fo:table- row> <xsl:for- each select="//monday/*"> <fo:block><xsl:apply- templates select="."/></fo:block> <fo:block /> </xsl:for- each> <xsl:for- each select="//tuesday/*"> <fo:block><xsl:apply- templates select="."/></fo:block> <fo:block /> </xsl:for- each> <xsl:for- each select="//wednesday/*"> <fo:block><xsl:apply- templates select="."/></fo:block> <fo:block /> </xsl:for- each> <xsl:for- each select="//thursday/*"> <fo:block><xsl:apply- templates select="."/></fo:block> <fo:block /> </xsl:for- each> <xsl:for- each select="//friday/*"> <fo:block><xsl:apply- templates select="."/></fo:block> <fo:block /> </xsl:for- each> </fo:table- row> </fo:table- body> </fo:table> </fo:flow></fo:page- sequence> 34
</fo:root> </xsl:template> <xsl:template match="lecture"> <xsl:value- of select="@rme"/> <xsl:text> {</xsl:text> <xsl:value- of select="@room"/> <xsl:text>}: </xsl:text> <xsl:value- of select="name()"/> <xsl:text>: </xsl:text> <xsl:value- of select="."/> </xsl:template> <xsl:template match="meerng"> <xsl:value- of select="@rme"/> <xsl:text> {</xsl:text> <xsl:value- of select="@room"/> <xsl:text>}: </xsl:text> <xsl:value- of select="name()"/> <xsl:text>: </xsl:text> <xsl:value- of select="."/> </xsl:template> <xsl:template match="lab"> <xsl:text> </xsl:text> <xsl:value-of select="@time"/> <xsl:text> {</xsl:text> <xsl:value-of select="@room"/> <xsl:text>}: </xsl:text> <xsl:value-of select="name()"/> <xsl:text>: </xsl:text> <xsl:value-of select="."/> </xsl:template> <xsl:template match="project"> <xsl:value-of select="@time"/> <xsl:text> {</xsl:text> <xsl:value-of select="@room"/> <xsl:text>}: </xsl:text> <xsl:value-of select="name()"/> <xsl:text>: </xsl:text> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet> 35
Wygenerowanie pliku PDF wymaga podania 3 parametrów (dane: XML, arkusz stylu:xsl z FO oraz format docelowy PDF) do procesora XSL- FO: fop - c conf/fop.xconf - xml workplan.xml - xsl workplanjwr.xsl workplanjwr.pdf 36
Tworzenie arkuszy stylów z XSL FO daje bardzo dużo możliwości, lecz jest pracochłonne. Gotowy arkusz można znacznie szybciej uzyskać stosują gotowe programy wspomagające projektowanie układu stron metoda WYSIWYG (ang. What You See Is What You Get to co widzisz, będzie tym co otrzymasz). Przykładem takiego programu jest Ecrion, XF Designer. 37
Wynik transformacji: 38
Podsumowanie Projekt Przygotowanie i realizacja kierunku inżynieria biomedyczna studia międzywydziałowe współfinansowany ze środków Unii Europejskiej w ramach Europejskiego Funduszu Społecznego.