The first two XMLC features to be covered are the most common ones used. These involve marking up an HTML template with valid but little-used HTML 4.0 elements: The id attribute and <SPAN> tags. These two elements may be created in HTML builder tools which are HTML 4.0 compliant.
id attributes are used to name HTML tags in such a way that XMLC can find them. Once a reference to the tag is established, XMLC working in conjunction with the W3C DOM Java classes can provide access methods which are appropriate to the given tag type. That is, an HTML header will have access methods which make sense for an HTML header.
However, having access to HTML tags may not be sufficient. What if we wish to dynamically generate bits of text in an HTML document? For that, we use <SPAN> tags. Any text that we may wish to change is surrounded by <SPAN> tags. It should be noted that an opening <SPAN> tag also has an id attribute.
Since it is envisaged that most HTML that is created as input to XMLC will be done with HTML design tools, it should be noted that not all design tools support HTML 4.0. If you are using an older design tool, you may not be able to add <SPAN> tags directly. Most design tools do have a facility to allow one to add new or unsupported tags, however.
It should be noted that all id attributes must be given a name that is unique within the HTML document. These names must also be legal Java identifiers, since they will be used as (or part of) Java variable names. To review, legal Java identifiers are case sensitive and must begin with a letter, an underscore ('_') or a dollar sign ('$'). Subsequent characters can also be numbers ('0-9'). Naturally, Java identifiers cannot clash with Java reserved words (e.g. 'abstract' or 'boolean').
<HTML> <HEAD> <TITLE>Hello, World</TITLE> </HEAD> <BODY BGCOLOR=#FFFFFF TEXT="#000000"> <H1>Hello, World</H1> This is a text of XMLC, showing how one can change text located in SPAN tags. Text outside of those tags and not within another tag with an id attribute cannot be changed. </BODY> </HTML>
Now, let's make some minor changes to the page so that XMLC can access it contents in an efficient manner. Note that XMLC depends on legal HTML/XML markup that will not interfere with other uses of the tags. HTML browsers are required to ignore tags and attributes that they do not understand or use.
<HTML> <HEAD> <TITLE id="title">Hello, World</TITLE> </HEAD> <BODY BGCOLOR=#FFFFFF TEXT="#000000"> <H1>Hello, World</H1> <SPAN id="para1">This is a text of XMLC, showing how one can change text located in SPAN tags.</SPAN> Text outside of those tags and not within another tag with an id attribute cannot be changed. </BODY> </HTML>
All that we have added is an single id attribute to the header, called "header1", and a <SPAN> tag surrounding part of the text, called "para1". We will show how these minor additions allow XMLC to create Java code that can manipulate these parts of the document.
$ $ENHYDRA/output/bin/xmlc -dump hello.html
If we look at the DOM for the first HTML page (without the id attribute or <SPAN> tag), we see a familiar looking structure which represents the HTML:
DOM hierarchy: BasicHTMLDocument BasicHTMLHtmlElement: html BasicHTMLHeadElement: head BasicHTMLTitleElement: title BasicText: text=Hello, World BasicHTMLBodyElement: body: bgcolor='#FFFFFF' text='#000000' BasicHTMLHeadingElement: h1 BasicText: text=Hello, World BasicText: text=This is a text of XMLC, showing how one can change text located in SPAN tags. Text outside of those tags and not within another tag with an id attribute cannot be changed.
If we look at the DOM for the second HTML page, we will see some nice additions:
DOM hierarchy: BasicHTMLDocument BasicHTMLHtmlElement: html BasicHTMLHeadElement: head BasicHTMLTitleElement: title: id='title' BasicText: text=Hello, World BasicHTMLBodyElement: body: bgcolor='#FFFFFF' text='#000000' BasicHTMLHeadingElement: h1 BasicText: text=Hello, World BasicHTMLElement: span: id='para1' BasicText: text= This is a text of XMLC, showing how one can change text located in SPAN tags. BasicText: text= Text outside of those tags and not within another tag with an id attribute cannot be changed.
The DOM now shows an id for the heading. You will also notice that the paragraph text is split into two parts. The bit outside of the <SPAN> tag is represented in a BasicText element, as before. The part within the <SPAN>, however, now has a BasicHTMLElement element, including an id and and an associate BasicText all to its own. We shall see what happens to those ided elements in the Java code shortly.
$ $ENHYDRA/output/bin/xmlc -keep hello.html
This will create both an compiled Java class file ('hello.class') and a source code file ('hello.java').
The Java class that results from the above example provides us with access to each element named with an id or a <SPAN>. Although it may look a bit strange to you if you are not yet comfortable with Java, don't be concerned. We will show you the important parts. Here is 'hello.java':
/* ************************************ * XMLC GENERATED CODE, DO NOT EDIT * ************************************ */ import org.w3c.dom.*; import org.enhydra.xml.xmlc.XMLCUtil; public class hello extends org.enhydra.xml.xmlc.html.HTMLObject { private static Document protoDocument; org.w3c.dom.html.HTMLTitleElement $elementtitle; org.w3c.dom.html.HTMLElement $elementpara1; static private void initProtoDom() { Node $node0, $node1, $node2, $node3; Element $elem0, $elem1, $elem2; Attr $attr0, $attr1, $attr2; com.docuverse.dom.DOM $$dom = new com.docuverse.dom.DOM(); com.docuverse.dom.html.HTMLFactory $$factory = new com.docuverse.dom.html.HTMLFactory(); $$dom.setFactory($$factory); protoDocument = (Document)$$factory.createDocument($$dom, "HTML"); $elem0 = protoDocument.createElement("html"); protoDocument.appendChild($elem0); $elem1 = protoDocument.createElement("head"); $elem0.appendChild($elem1); $elem2 = protoDocument.createElement("title"); $elem1.appendChild($elem2); $attr2 = protoDocument.createAttribute("id"); $attr2.setValue("title"); $elem2.setAttributeNode($attr2); $node3 = protoDocument.createTextNode("Hello, World"); $elem2.appendChild($node3); $elem1 = protoDocument.createElement("body"); $elem0.appendChild($elem1); $attr1 = protoDocument.createAttribute("text"); $attr1.setValue("#000000"); $elem1.setAttributeNode($attr1); $attr1 = protoDocument.createAttribute("bgcolor"); $attr1.setValue("#FFFFFF"); $elem1.setAttributeNode($attr1); $elem2 = protoDocument.createElement("h1"); $elem1.appendChild($elem2); $node3 = protoDocument.createTextNode("Hello, World"); $elem2.appendChild($node3); $elem2 = protoDocument.createElement("span"); $elem1.appendChild($elem2); $attr2 = protoDocument.createAttribute("id"); $attr2.setValue("para1"); $elem2.setAttributeNode($attr2); $node3 = protoDocument.createTextNode(" This is a text of XMLC, showing how one can change text located in SPAN tags."); $elem2.appendChild($node3); $node2 = protoDocument.createTextNode(" Text outside of those tags and not within another tag with an id attribute cannot be changed."); $elem1.appendChild($node2); } static { initProtoDom(); } public hello() { super(protoDocument); $elementtitle = (org.w3c.dom.html.HTMLTitleElement)this.getElementById("title"); $elementpara1 = (org.w3c.dom.html.HTMLElement)this.getElementById("para1"); } /** * Get the value of element title. * @see org.w3c.dom.html.HTMLTitleElement */ public org.w3c.dom.html.HTMLTitleElement getElementTitle() { return $elementtitle; } /** * Get the value of element para1. * @see org.w3c.dom.html.HTMLElement */ public org.w3c.dom.html.HTMLElement getElementPara1() { return $elementpara1; } /** * Get the value of text child of element para1. * @see org.w3c.dom.Text */ public void setTextPara1(String str) { XMLCUtil.getFirstText($elementpara1).setData(str); } }
The first thing to notice is that this class extends org.enhydra.xml.xmlc.html.HTMLObject. If we look at that class, we find that it is an abstract class which provides a number of useful methods. Since our class extends that abstract class, we gain access to all of those methods. The most interesting one is:
The next thing to notice is the text that we have set in red. These methods extend the methods available to any HTMLObject. Note that we have been given a getElement* method for every HTML element that we gave an id attribute. We also have a getElement* and setText* methods for every bit of text that we surrounded with <SPAN> tags.
We have getElement* methods for:
If we look at the Javadoc for org.w3c.dom.html.HTMLTitleElement, we would see all of the methods we can call to manipulate our HTML page's title, "title". The next section shows an example of this.
Similarly, the text that we wrapped in <SPAN> tags has a method called getElementPara1(), which returns just an org.w3c.dom.html.HTMLElement object.
The setText* methods for <SPAN> tags is necessary since they refer to text that is not properly bounded by other tags. That is, a <SPAN> refers to a subset of a paragraph tag. XMLC uses the <SPAN> tags as a cue to create the necessary methods.
import org.w3c.dom.html.*; public class hello_creator { public static void main (String[] args) { // Create an instance of the HTML page object. hello hello = new hello(); // Get a reference to the header and change it. HTMLTitleElement title = hello.getElementTitle(); title.setText("Hello, New World!"); // Change some text within the <SPAN> tags. hello.setTextPara1("We changed this!"); // Print out the results. System.out.print( hello.toDocument() ); } }
$ javac hello_creator.java $ java hello_creator
When the toDocument() method of the page class is finally called, it will create the HTML that the user will see. Here is the HTML page created by the above example:
<HTML> <HEAD> <TITLE>Hello, New World!</TITLE> </HEAD> <BODY BGCOLOR=#FFFFFF TEXT="#000000"> <H1>Hello, World</H1> We changed this! Text outside of those tags and not within another tag with an id attribute cannot be changed. </BODY> </HTML>
You should note that the HTML that is actually generated does not maintain the formatting shown above. That is, there are no line separators or whitespace between the tags. This is most efficient for both network transport and machine parsing, but it does make it hard for a human to read. We have included formatting here for ease of reading.
This example started life as a question on the Enhydra mailing list and was answered by Mark Diekhans.
If we wanted to replace <span id="replaceme"> Replace Me with some text </span> with some thing like <h1> Hello World <h1> <A HREF=Welcome.po> Welcome Page </A>
To add HTML elements to an XMLC generated object, which is a DOM Document object, you must create new DOM element objects and add them as children to the parent element.
To do this, use the createElement() method of the DOM Document. The following (untested) code demonstrates this:
HTMLObject htmlObj = new HelloHTML(); // Construct head HTMLHeadingElement head = htmlObj.createElement("h1"); Text headText = htmlObj.createText("Hello World"); head.appendChild(htmlTest); // Construct anchor HTMLAnchorElement anchor = htmlObj.createElement("a"); anchor.setHref("Welcome.po"); Text anchorText = htmlObj.createText("Welcome Page"); anchor.appendChild(anchorText); // Replace contents of id-labeled node. Element replace = htmlObj.getElementReplaceme(); Element parent = replace.getParent(); // Start with the last new child so we can use insertBefore parent.replaceChild(anchor, replace); parent.insertBefore(head, anchor);