[Previous] [Contents] [Next]


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:  &ltbiblio>
23:  &ltbooks>
24:       &ltbook id="TY1">
25:             &lttitle&gtSam's Teach Yourself C++ in 21 Days, Second Edition
26:             </title>
27:             &ltauthor&gtJesse Liberty
28:             </author>
29:             &ltdescription&gtThis 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:             &ltISBN&gt0-672-31070-8
32:             </ISBN>
33:             &ltpages&gt700
34:             </pages>
35:             &lttargetgroup&gtBeginning - Intermediate
36:             </targetgroup>
37:             &ltprice unit="USA"&gt29.99
38:             </price>
39:             &ltrelated linkend="TY2"&gtTeach Yourself Visual C++ 5
</related>
40:       </book>
41:         &ltbook id="MJ">
42:             &lttitle&gtMaximum Java 1.1
43:             </title>
44:             &ltauthor&gtGlenn Vanderburg
45:             </author>
46:             &ltdescription&gtWritten 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:             &ltISBN&gt1-57521-290-0
49:             </ISBN>
50:             &ltpages&gt900
51:             </pages>
52:             &lttargetgroup&gtExpert
53:             </targetgroup>
54:             &ltprice unit="USA"&gt49.99
55:             </price>
56:      </book>
57:      &ltbook id="JS">
58:             &lttitle&gtJavaScript Unleashed, Second Edition
59:             </title>
60:             &ltauthor&gtRichard Wagner
61:             </author>
62:             &ltdescription&gtThis book helps you thoroughly understand
and apply JavaScript.
63:             </description>
64:             &ltISBN&gt1-57521-306-0
65:             </ISBN>
66:             &ltpages&gt1000
67:             </pages>
68:             &lttargetgroup&gtCasual - Experienced
69:             </targetgroup>
70:             &ltprice&gt49.99
71:             </price>
72:       </book>
73:       &ltbook ID="TY2">
74:             &lttitle&gtSam's Teach Yourself Visual C++ 5 in 21 Days,
Fourth Edition
75:             </title>
76:             &ltauthor&gtNathan Gurewich
77:             </author>
78:             &ltauthor&gtOri Gurewich
79:             </author>
80:             &ltdescription&gtThis 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:             &ltISBN&gt0-672-31014-7
83:             </ISBN>
84:             &ltpages&gt832
85:             </pages>
86:             &lttargetgroup&gtNew - Casual
87:             </targetgroup>
88:             &ltprice&gt35.00
89:             </price>
90:       </book>
91:  </books>
92:  &ltauthors>
93:       &ltauthordesc>
94:             &ltname&gtJesse Liberty
95:             </name>
96:             &ltspecialty&gtC
97:             </specialty>
98:      </authordesc>
99:      &ltauthordesc>
100:            &ltname&gtGlenn Vanderburg
101:            </name>
102:            &ltspecialty&gtJava
103:            </specialty>
104:    </authordesc>
105:    &ltauthordesc>
106:            &ltname&gtRichard Wagner
107:            </name>
108:            &ltspecialty&gtOpera
109:            </specialty>
110:    </authordesc>
111:    &ltauthordesc>
112:            &ltname&gtNathan Gurewich
113:            </name>
114:            &ltspecialty&gtVisual Basic
115:            </specialty>
116:            &ltspecialty&gtVisual 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 "&ltHTML>%n"
5:       || "&ltHEAD>%n"
6:       || "&ltTITLE&gtMy bookshop</TITLE>%n"
7:       || "</HEAD>%n"
8:       || "&ltBODY>%n"
9:       || "&ltH1&gtMy bookshop</H1>%n&ltP>&ampnbsp;</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 "&ltHR>%n"
21:
22:  element title
23:      output "&ltH2 style='margin-top:40pt'>"
24:      using attribute id of parent
25:            do when attribute id is specified
26:            output "&ltA name='%v(id)'></A>"
27:            done
28:      output "%c</H2>%n"
29:
30:  element author
31:  do when previous is title
32:            output "&ltP>&ltI>%c</I>"
33:      else
34:            output "&ltBR>%n"
35:            || "&ltI>%c</I>"
36:      done
37:
38:  element description
39:      output "</P>%n" ; closing the p element started [cc]
with the first author
40:     || "&ltHR>%n"
41:     || "&ltP>%c</P>%n"
42:
43:  element ISBN
44:     output "&ltP>&ltCODE&gtISBN-number: %c</CODE>&ltBR>%n"
45:
46:  element pages
47:     output "%c pages&ltBR>%n"
48:
49:  element targetgroup
50:     output "Aimed at the '%c'&ltBR>%n"
51:
52:  element price
53:     output "%c US$</P>%n"
54:
55:  element related
56:     do when occurrence = 1
57:            output "&ltP>&ltI&gtSee also: </I>&ltBR>"
58:     done
59:     output "&ltA HREF='#%v(linkend)'>%c</A>&ltBR>"
60:
61:  element authors
62:     output "&ltH2 style='margin-top:40pt'&gtAn overview of
our writers</H2>%n"
63:     output "&ltTABLE CELLPADDING='5'>"
64:     output "&ltTR>&ltTH&gtName</TH>&ltTH&gtSpecialty</TH></TR>%n"
65:     output "%c</TABLE>%n"
66:
67:  element authordesc
68:     output "&ltTR>%c</I></TD></TR>%n"
69:
70:  element name
71:     output "&ltTD>%c</TD>%n"
72:
73:  element specialty
74:     do when occurrence = 1
75:            output "&ltTD>&ltI>%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
With this example, we're assuming that all files are in the same subdirectory as the omle.exe program.

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 "&ltHTML>%n"
7:              || output "&ltHEAD>%n"
8:              || output "&ltTITLE&gtBook %v(id)</TITLE>"%n
9:              || output "</HEAD>%n"
10:             || output "&ltBODY>%n"
11:             output "%c"
12:             do when last proper subelement is related
13:                    output "</P>"
14:             done
15:             output "&ltHR>%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 "&ltHTML>%n"
24:             || output "&ltHEAD>%n"
25:             || output "&ltTITLE&gtAuthors</TITLE>"%n
26:             || output "</HEAD>%n"
27:             || output "&ltBODY>%n"
28:             output "&ltH2 style='margin-top:40pt'&gtAn overview of our
writers</H2>%n"
29:             output "&ltTABLE CELLPADDING='5'>"
30:             output "&ltTR>&ltTH&gtName</TH>&ltTH&gtSpecialty</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

&ltA HREF="#TY2"&gt.

needs to be changed to the following:

&ltA HREF="TY2.htm">

We change the Omnimark script:

55  element related
       ...
59     output "&ltA HREF='%v(linkend).htm'>%c</A>&ltBR>"

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 "&ltHTML>%n"
5:       || "&ltHEAD>%n"
6:       || "&ltTITLE&gtMy bookshop</TITLE>%n"
7:       || "</HEAD>%n"
8:       || "&ltBODY>%n"
9:       || "&ltH1&gtMy bookshop</H1>%n&ltP></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 "&ltHR>&ltH3&gtTable of Contents</H3>%n&ltUL>"
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 "&ltH2 style='margin-top:40pt'>"
10:       using attribute id of parent
11:              do when attribute id is specified
12:              output "&ltA 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 "&ltLI>&ltA 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 "&ltHR>%n"
11:              output "%g(prevpage)" ; here we add our previous link
12:              set prevpage to "&ltP>&ltA
HREF='%v(id).htm'&gtPrevious</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 "&ltA
HREF='%v(id).htm'&gtNext</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 "&ltHR>%n"
17:              output "%g(prevpage)"         ; the info of previous page
18:              output referent "next-%v(id)" ; our placeholder
19:              set prevpage to "&ltP>&ltA
HREF='%v(id).htm'&gtPrevious</A>&ampnbsp; &ampnbsp;"
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.

[Previous] [Contents] [Next]