An Example of an Omnimark Script
|
Listing 15.14 biblio.xml-The xml File to Convert to HTML
|
1: <?xml version="1.0"?> 2: <!DOCTYPE biblio [ 3: <!ELEMENT biblio (books, authors)> 4: <!ELEMENT books (book)+ > 5: <!ELEMENT book (title, author+, description, ISBN, pages, targetgroup, price, related*) > 6: <!ATTLIST book id ID #REQUIRED> 7: <!ELEMENT title (#PCDATA) > 8: <!ELEMENT author (#PCDATA) > 9: <!ELEMENT description (#PCDATA) > 10: <!ELEMENT ISBN (#PCDATA) > 11: <!ELEMENT pages (#PCDATA) > 12: <!ELEMENT targetgroup (#PCDATA) > 13: <!ELEMENT price (#PCDATA) > 14: <!ATTLIST price unit CDATA "USA"> 15: <!ELEMENT related (#PCDATA) > 16: <!ATTLIST related linkend IDREF #REQUIRED> 17: <!ELEMENT authors (authordesc)+ > 18: <!ELEMENT authordesc (name, specialty+) > 19: <!ELEMENT name (#PCDATA)> 20: <!ELEMENT specialty (#PCDATA)> 21: ]> 22: <biblio> 23: <books> 24: <book id="TY1"> 25: <title>Sam's Teach Yourself C++ in 21 Days, Second Edition 26: </title> 27: <author>Jesse Liberty 28: </author> 29: <description>This book teaches you the basics of object-oriented programming with C++ and is completely revised to ANSI standards. It can be used with any C++ compiler. 30: </description> 31: <ISBN>0-672-31070-8 32: </ISBN> 33: <pages>700 34: </pages> 35: <targetgroup>Beginning - Intermediate 36: </targetgroup> 37: <price unit="USA">29.99 38: </price> 39: <related linkend="TY2">Teach Yourself Visual C++ 5 </related> 40: </book> 41: <book id="MJ"> 42: <title>Maximum Java 1.1 43: </title> 44: <author>Glenn Vanderburg 45: </author> 46: <description>Written by JAVA experts, this book explores the JAVA 1.1 language, tools, and core JAVA API without reviewing fundamentals or basic techniques. 47: </description> 48: <ISBN>1-57521-290-0 49: </ISBN> 50: <pages>900 51: </pages> 52: <targetgroup>Expert 53: </targetgroup> 54: <price unit="USA">49.99 55: </price> 56: </book> 57: <book id="JS"> 58: <title>JavaScript Unleashed, Second Edition 59: </title> 60: <author>Richard Wagner 61: </author> 62: <description>This book helps you thoroughly understand and apply JavaScript. 63: </description> 64: <ISBN>1-57521-306-0 65: </ISBN> 66: <pages>1000 67: </pages> 68: <targetgroup>Casual - Experienced 69: </targetgroup> 70: <price>49.99 71: </price> 72: </book> 73: <book ID="TY2"> 74: <title>Sam's Teach Yourself Visual C++ 5 in 21 Days, Fourth Edition 75: </title> 76: <author>Nathan Gurewich 77: </author> 78: <author>Ori Gurewich 79: </author> 80: <description>This book merges the power of the best- selling "Teach Yourself" series with the knowledge of Nathan and Ori Gurewich, renowned experts in code, creating the most efficient way to learn Visual C++. 81: </description> 82: <ISBN>0-672-31014-7 83: </ISBN> 84: <pages>832 85: </pages> 86: <targetgroup>New - Casual 87: </targetgroup> 88: <price>35.00 89: </price> 90: </book> 91: </books> 92: <authors> 93: <authordesc> 94: <name>Jesse Liberty 95: </name> 96: <specialty>C 97: </specialty> 98: </authordesc> 99: <authordesc> 100: <name>Glenn Vanderburg 101: </name> 102: <specialty>Java 103: </specialty> 104: </authordesc> 105: <authordesc> 106: <name>Richard Wagner 107: </name> 108: <specialty>Opera 109: </specialty> 110: </authordesc> 111: <authordesc> 112: <name>Nathan Gurewich 113: </name> 114: <specialty>Visual Basic 115: </specialty> 116: <specialty>Visual C++ 117: </specialty> 118: </authordesc> 119: </authors> 120: </biblio>
We name this file biblio.xml and will write a script to convert the XML into HTML.
We first write event handlers to convert every XML element to a HTML element, as shown in Listing 15.15.
Listing 15.15 tohtml.xml-Our Omnimark Script to Convert the File biblio.xml to HTML
1: DOWN-TRANSLATE with XML 2: 3: element biblio 4: output "<HTML>%n" 5: || "<HEAD>%n" 6: || "<TITLE>My bookshop</TITLE>%n" 7: || "</HEAD>%n" 8: || "<BODY>%n" 9: || "<H1>My bookshop</H1>%n<P>&nbsp;</P>%n" 10: || "%c" ; continue parsing 11: 12: element books 13: output "%c" 14: 15: element book 16: output "%c" 17: do when last subelement is related 18: output "</P>" 19: done 20: output "<HR>%n" 21: 22: element title 23: output "<H2 style='margin-top:40pt'>" 24: using attribute id of parent 25: do when attribute id is specified 26: output "<A name='%v(id)'></A>" 27: done 28: output "%c</H2>%n" 29: 30: element author 31: do when previous is title 32: output "<P><I>%c</I>" 33: else 34: output "<BR>%n" 35: || "<I>%c</I>" 36: done 37: 38: element description 39: output "</P>%n" ; closing the p element started [cc] with the first author 40: || "<HR>%n" 41: || "<P>%c</P>%n" 42: 43: element ISBN 44: output "<P><CODE>ISBN-number: %c</CODE><BR>%n" 45: 46: element pages 47: output "%c pages<BR>%n" 48: 49: element targetgroup 50: output "Aimed at the '%c'<BR>%n" 51: 52: element price 53: output "%c US$</P>%n" 54: 55: element related 56: do when occurrence = 1 57: output "<P><I>See also: </I><BR>" 58: done 59: output "<A HREF='#%v(linkend)'>%c</A><BR>" 60: 61: element authors 62: output "<H2 style='margin-top:40pt'>An overview of our writers</H2>%n" 63: output "<TABLE CELLPADDING='5'>" 64: output "<TR><TH>Name</TH><TH>Specialty</TH></TR>%n" 65: output "%c</TABLE>%n" 66: 67: element authordesc 68: output "<TR>%c</I></TD></TR>%n" 69: 70: element name 71: output "<TD>%c</TD>%n" 72: 73: element specialty 74: do when occurrence = 1 75: output "<TD><I>%c" 76: else 77: output " - %c" 78: done 79: 80: document-end 81: output "</BODY></HTML>"
We save this script as tohtm.xom.
| You see that we have defined an element rule for every XML element. |
Previously we have only seen conditions as part of the rule header, but conditions can also be inserted in the rule body where the actions are defined. Refer to element specialty on line 73, where you find, starting on line 74, a do when..., else..., done construct, where a difference is made between an element specialty appearing first in a row of specialty elements and those specialty elements coming later.
Lines 24, 25, and 26 also deserve some explanation. For the element title, examine the attribute with name id of the parent of title, being book (line 24). If this attribute id has a value specified (line 25), write an HTML anchor to the output with an attribute name that has the value of this id (line 26).
Now we run from the command line:
omle -s tohtml.xom biblio.xml -of biblio.htm
|
This generates the file biblio.htm, as shown in Figure 15.1.
Figure 15.1 The result of our first conversion.
Let's try to split up the file and make a separate HTML file for each book and a separate file for the author's overview.
We need to change the code for two elements: book and authors, as shown in Listing 15.6.
Listing 15.16 tohtml.xml-Conversion to Multiple HTML Files
1: element book 2: local stream bookhtm ;creating a variable with name "bookhtm"" of type stream 3: open bookhtm as file "%v(id).htm" ; this stream is written to a file, based on the id of the book element 4: using output as bookhtm ; now we write the output to this stream (file) 5: do ;everything between 'do' and 'done' needs to go to the stream 6: output "<HTML>%n" 7: || output "<HEAD>%n" 8: || output "<TITLE>Book %v(id)</TITLE>"%n 9: || output "</HEAD>%n" 10: || output "<BODY>%n" 11: output "%c" 12: do when last proper subelement is related 13: output "</P>" 14: done 15: output "<HR>%n" 16: output "</BODY></HTML>%n" 17: done 18: 19: element authors 20: local stream authorshtm 21: open authorshtm as file "authors.htm" 22: using output as authorshtm 23: output "<HTML>%n" 24: || output "<HEAD>%n" 25: || output "<TITLE>Authors</TITLE>"%n 26: || output "</HEAD>%n" 27: || output "<BODY>%n" 28: output "<H2 style='margin-top:40pt'>An overview of our writers</H2>%n" 29: output "<TABLE CELLPADDING='5'>" 30: output "<TR><TH>Name</TH><TH>Specialty</TH></TR>%n" 31: output "%c</TABLE>%n" 32: output "</BODY></HTML>%n" 33: done
| For each book element we declare a local variable of type stream with the name bookhtm. On line 3 we open the stream as a file whose name is given by the string expression %v(id).htm, which is the value of the attribute id, or TY1 for the first book in our XML file. This is followed by .htm, resulting in TY1.htm. On line 4 we write our output to this file. Because we are writing to different files now we need to add the appropriate HTML start and closing information in each file, hence lines 6 to 10 and 16. The same principles have been applied to the element authors. |
We run the program again, which results in the generation of 6 files.
The resulting files are
- • biblio.htm
- • TY1.htm
- • MJ.htm
- • JS.htm
- • TY2.htm
- • authors.htm
This is nice but we have two problems:
- 1. The link generated by the event handler of the related element doesn't work anymore. It was coded as a link to a place inside the same document. Now it must become a link to a different document.
-
2. We're missing navigation aids to move to the different files. Our wish is twofold:
- • To have a TOC inside the first biblio.htm file with an overview of all the books
- • Links on each page for going to the previous or next book
We first solve the broken link issue.
The link in the same file to this anchor
<A HREF="#TY2">.
needs to be changed to the following:
<A HREF="TY2.htm">
We change the Omnimark script:
55 element related
...
59 output "<A HREF='%v(linkend).htm'>%c</A><BR>"
Remember that referents are just placeholders that have content defined later on.
For generating a TOC we first add a global stream variable, to be used as a referent to our script, as shown in Listing 15.17.
Listing 15.17 tohtml.xml-Adding a TOC
1: global stream toc; to be used later on as a referent 2: 3: element biblio 4: output "<HTML>%n" 5: || "<HEAD>%n" 6: || "<TITLE>My bookshop</TITLE>%n" 7: || "</HEAD>%n" 8: || "<BODY>%n" 9: || "<H1>My bookshop</H1>%n<P></P>%n" 10: 11: output referent "toc" ; here we will (out)put our toc 12: 13: open toc as referent "toc" ; and we initialise it 14: put toc "<HR><H3>Table of Contents</H3>%n<UL>" 15: close toc 16: 17: output "%c" ; continue parsing
If you try this out, you will receive the title "Table of Contents" in your biblio.htm file.
| In line 11 we asked to output the content of our placeholder with the name "toc". This placeholder has been filled in lines 13 to 15 with the title (line 14). |
We need to add the titles of our books to the toc, so we need to write additional information in our placeholder toc every time we encounter a book title, as shown in Listing 15.18.
Listing 15.18 tohtml.xml-Filling the TOC
1: element title 2: ; putting the content into this variable since we will use this content twice 3: local stream titlecontent ; creating a variable of type stream 4: open titlecontent as buffer 5: put titlecontent "%c" 6: close titlecontent 7: 8: ; existing code 9: output "<H2 style='margin-top:40pt'>" 10: using attribute id of parent 11: do when attribute id is specified 12: output "<A name='%v(id)'></A>" 13: done 14: output "%g(titlecontent)</H2>%n" 15: 16: ; referent 17: reopen toc as referent "toc" 18: using attribute id of parent 19: put toc "<LI><A HREF='%v(id).htm'>%g(titlecontent)</A></LI>" 20: close toc
| First we put the content of our title inside a local variable with the name titlecontent (lines 3-7). This buffered content is used in line 15 and will be output into an H2 HTML element. |
But the most important part starts at line 18, where our placeholder toc is reopened and the content on line 20 is added to the already existing content of our referent.
| The result is shown in Figure 15.2. |
Figure 15.2 The TOC generated by our script.
Next comes the addition of next and previous navigation links at the bottom of each page.
Let's start with a link to the previous page. Because we have already passed this page, we were able to buffer this information and use it on our current page, as done in Listing 15.19.
Listing 15.19 tohtml.xml-Including Link to Previous Page
1: element book 2: local stream bookhtm 3: open bookhtm as file "%v(id).htm" 4: using output as bookhtm 5: do 6: output "%c" 7: do when last proper subelement is related 8: output "</P>" 9: done 10: output "<HR>%n" 11: output "%g(prevpage)" ; here we add our previous link 12: set prevpage to "<P><A HREF='%v(id).htm'>Previous</A></P>" 13: ; and we keep the information of this page for the next one 14: done
| On line 12 we set the content of the prevpage variable to a link containing the name of our actual HTML page. It is this content that will be used on line 11 for the next page. |
Listing 15.20 shows how to create the link to the next page. This needs a referent.
Listing 15.20 tohtml.xml-Including Link to Next Page
1: element book 2: local stream bookhtm 3: set referent "next-%v(id)" to "" 4: ; the next on this page is set to empty 5: ; this is done since we don't know yet if there is a next page 6: set referent "next-%g(previd)" to "<A HREF='%v(id).htm'>Next</A>" 7: ; the next of previous page gets the info of this (being next) page 8: open bookhtm with referents-allowed as file "%v(id).htm" 9: ; referents-allowed added since we put placeholders in this stream now 10: using output as bookhtm ; writing to the file 11: do 12: output "%c" 13: do when last proper subelement is related 14: output "</P>" 15: done 16: output "<HR>%n" 17: output "%g(prevpage)" ; the info of previous page 18: output referent "next-%v(id)" ; our placeholder 19: set prevpage to "<P><A HREF='%v(id).htm'>Previous</A>&nbsp; &nbsp;" 20: set previd to "%v(id)" ; used in next page for filling in placeholder 21: done
| After the output of our previous link, we output a link to our next page, only we don't know its content, hence the referent used on line 18. The name of this referent refers to the id value of the book. |
Because we also don't know at this level if there will be a next page, we initially set the content of our link to the next page to the empty string "" (line 3). If a next page exists, this content will be overwritten by the action on line 6. Notice that we capture the id of the book at the end of the rule body in the previd variable. This value is used in line 6 to fill in the placeholder on the previous page.
| The result is shown in Figure 15.3. |
Figure 15.3 Our generated HTML files with navigation links.