Enhydra之XMLC的使用
错误和疑问请发到zy.wang@263.net
XMLC是Enhydra中表现层的核心技术,XMLC是一个为动态网站内容开发使用的模版生成器,它完全基于xml/dom和java标准。它提供了一个从静态html和xml模板文件生成动态内容的java对象的机制。这个对象就把模版文件DOM化了,我们可以通过java/dom来操作这个java对象,从而实现动态的web内容显示。运用XMLC,我们完全可以把显示逻辑和商业逻辑完全的分开而不会再出现html文件中夹杂程序代码的情况,在html文件中你不用放入任何的java代码,这在在aps/jsp/php中是不可想象的,我们可以专心开发程序,界面丢给美工好了。所以接触到这个东西,我对嵌入网页的脚本就再也提不起兴趣了--有人要拿砖头了:)。好了让我们开始吧!
一、理解DOM概念
我们都知道xml/html文件有着树状的层次结构,并且它的模型可以用某种面向对象的程序语言(例如java)来表现。w3c把这种xml/html对象模型的标准称为文档对象模型(DOM),它是基于xml的一种标准。举个例子:
对于如下html代码
|
<TABLE> <TR> <TD ID=”cellOne”>张三</TD> <TD ID=”cellTwo”>李四</TD> </TR> <TR> <TD ID=”cellThree”>王五</TD> <TD ID=”cellFour”>赵六</TD> </TR> </TABLE> |
我们可以看见了一棵的DOM树(如下图),TABLE为树根,然后从树根出来时TR到最末端TD。节点连接的上个节点是父节点,连接的下层节点是子节点。每个标记是一个树的节点。某些每个节点有自己的属性,例如TABLE会有背景色、宽度等等属性。w3c定义了这些html对象节点的对象和接口的标准,enhydra的api就遵循这些标准或者使用其api,所以在enhydra我们可以控制这些dom对象节点的属性操作。
举个例子,我们要设置上面的表格中张三这个格的背景色为红色的话,可以这么做
HTMLTableCellElement cellOne = theDocument.getElementCellOne();
cellOne.setBgColor(“red”);
类HTMLTableCellElement和方法setBgColor是从w3c的java包得到的,而getElementCellOne则是xmlc为我们提供的。可以看到,xmlc创建了访问dom树结点的方法。xmlc从模版文件中生成getElementxxx()的方法来返回对应于模版文件ID="xxx"节点的java对象。然后用这个对象的方法,我们可以操作对象对应的文档节点的属性。
二、创建模版文件
1、
在这里我们先要介绍一下xmlc模版文件是怎样的?
在html文件中,标记span和div只是用来提供给css样式表,除此之外浏览器对这两个标记并不处理,因此xmlc把span用于动态生成一段字,div则用来动态生成任何东西,比如生成表格和文字图片的混合树。另外,如果你想控制某个html节点,你可以在任何一个html标记添加id。
2、
一个例子
我们来看一个静态html文件:hello.html:
<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>
|
我们想在程序运行的时候动态改变TITLE和BODY的内容,相应的模版就如下
<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>
|
红色部分就是加入的模版标记,用浏览器看一下,和没加标记的效果是一样的。
三、使用xmlc编译模版文件
有了模版文件,现在就要编译它了。
模版编译是把html/xml转化成对应DOM树的java对象的过程,这个通过xmlc这个程序来完成。它的使用非常的简单,用法如下:
把enhydra.jar加入CLASSPATH
在unix下
export CLASSPATH=<enhyra_root>/lib/enhydra.jar:.
在windows下
set CLASSPATH=<enhydra_root>/lib/enhydra.jar
a)
然后使用xmlc命令
语法如下:
xmlc -参数 模版文件.html
主要的参数有:
-class
生成的全类名例如:xxx.xxx.classname
-keep
保留生成的java源文件
-sourceout
生成的java源程序的根路径
-html:encoding 这个比较重要,设置成你的文件编码,如GB2312
其他一些参数请参考Enhydra得文档
b)
使用jbuilder+khelp
Enhydra提供了支持Jbuilder的开发插件,只要在安装完Enhydra和Jbuilder后,安装Khelp就可以了。在Khelp下使用xmlc就更简单了。在菜单wiizards中选择xmlc compiler…,
在弹出的对话框中我们可以看到选项设置,如下图,设置好选项后,我们在selections中把模版文件选入,然后编译就可以了。
四、使用xmlc生成的java对象
察看生成的代码hello.java
|
/* ************************************ * XMLC GENERATED CODE, DO NOT EDIT * ************************************ */ import org.w3c.dom.*; import org.enhydra.xml.xmlc.XMLCUtil; import org.enhydra.xml.xmlc.XMLCError; import org.enhydra.xml.xmlc.dom.XMLCDomFactory; public class hello extends org.enhydra.xml.xmlc.html.HTMLObjectImpl
{ /** * Field that is used
to identify this as an XMLC * generated class.
Contains an reference to the * class object. */ public static final Class
XMLC_GENERATED_CLASS = hello.class; /** * Field containing
CLASSPATH relative name of the source file * that this class was
generated from. */ public static final String
XMLC_SOURCE_FILE = "nullhello.html"; /** * Get the element with
id para1. * @see org.w3c.dom.html.HTMLElement */ public org.w3c.dom.html.HTMLElement
getElementPara1() { return
$elementpara1; } private org.w3c.dom.html.HTMLElement
$elementpara1; /** * Get the value of
text child of element para1. * @see org.w3c.dom.Text */ public void setTextPara1(String text) { XMLCUtil.getFirstText($elementpara1).setData(text); } /** * Get the element with
id title. * @see org.w3c.dom.html.HTMLTitleElement */ public org.w3c.dom.html.HTMLTitleElement
getElementTitle() { return
$elementtitle; } private org.w3c.dom.html.HTMLTitleElement
$elementtitle; /** * Create document as
a DOM and initialize accessor method fields. */ public void buildDocument()
{ XMLCDomFactory
domFactory = org.enhydra.xml.xmlc.dom.XMLCDomFactoryCache.getFactory("org.enhydra.xml.xmlc.dom.DefaultHTMLDomFactory"); Document
document = domFactory.createDocument(null, null); setDocument(document); domFactory.setErrorChecking(document,
false); Node
$node0, $node1, $node2, $node3; Element
$elem0, $elem1, $elem2; Attr
$attr0, $attr1, $attr2; $elem0
= document.getDocumentElement(); $elem1
= document.createElement("HEAD");; $elem0.appendChild($elem1); $elem2
= document.createElement("TITLE");; $elem1.appendChild($elem2); $elementtitle
= (org.w3c.dom.html.HTMLTitleElement)$elem2; $attr2
= document.createAttribute("id"); $elem2.setAttributeNode($attr2); $node3
= document.createTextNode("title");; $attr2.appendChild($node3); $node3
= document.createTextNode("Hello, World");; $elem2.appendChild($node3); $elem1
= document.createElement("BODY");; $elem0.appendChild($elem1); $attr1
= document.createAttribute("bgcolor"); $elem1.setAttributeNode($attr1); $node2
= document.createTextNode("#FFFFFF");; $attr1.appendChild($node2); $attr1
= document.createAttribute("text"); $elem1.setAttributeNode($attr1); $node2
= document.createTextNode("#000000");; $attr1.appendChild($node2); $elem2
= document.createElement("H1");; $elem1.appendChild($elem2); $node3
= document.createTextNode("Hello, World");; $elem2.appendChild($node3); $elem2
= document.createElement("SPAN");; $elem1.appendChild($elem2); $elementpara1
= (org.w3c.dom.html.HTMLElement)$elem2; $attr2
= document.createAttribute("id"); $elem2.setAttributeNode($attr2); $node3
= document.createTextNode("para1");; $attr2.appendChild($node3); $node3
= document.createTextNode("This is a text of XMLC, showing how
one can change text located in SPAN tags.");; $elem2.appendChild($node3); $node2
= document.createTextNode(" Text outside of those tags and not
within another tag with an id attribute cannot be changed.");; $elem1.appendChild($node2); domFactory.setErrorChecking(document,
true); } /** * Recursize function
to do set access method fields from the DOM. * Missing ids have
fields set to null. */ protected void syncWithDocument(Node
node) { if
(node instanceof Element) {
String id = ((Element)node).getAttribute("id");
if (id.length() == 0) {
} else if (id.equals("para1")) {
$elementpara1 = (org.w3c.dom.html.HTMLElement)node;
} else if (id.equals("title")) {
$elementtitle = (org.w3c.dom.html.HTMLTitleElement)node;
} } } /** * Default constructor. */ public hello() { buildDocument(); } /** * Constructor with
optional building of the DOM. * * @param buildDOM If
false, the DOM will not be built until * buildDocument() is
called by the derived class. If
true, * the DOM is built
immediatly. */ public hello(boolean buildDOM)
{ if
(buildDOM) {
buildDocument(); } } /** * Copy constructor. * @param src The document
to clone. */ public hello(hello src) { setDocument((Document)src.getDocume |