极品桌面
极品网文
极品日记
访客留言
加载中...
网文首页
精妙网文
爆笑网文
网页制作
小说连载
ASP
网页技术
网站相关
XML
建站经验
PHP
MS SQL
查看文章
用xml和xsl来生成动态页面
作者:未知 来源:未知 添加时间:2006年7月3日 字体:
大
中
小
81270
文:jason monberg
L0bK4Vp
译:马晓宁
L0bK4Vp
L0bK4Vp
xml(可扩展标记语言)看起来可能像某种w3c标准——现在没有什么实际影响,即使以后能派上用场,也是很久以后的事。但实际上,它现在已经得到了应用。所以,不要等到xml已被加进了你最喜爱的html编辑器中才开始使用它。它现在就可以解决各种内部问题和b2b系统问题。
L0bK4Vp
L0bK4Vp
在sparks.com,我
L0bK4Vp
们使用xml来标准化从java对象到html数据显示等不同系统之间的数据表示。
L0bK4Vp
L0bK4Vp
特别需要指出的是,我
L0bK4Vp
们发现,只要以非常基本的xml结构来实现标准化,就可以更容易地共享和操作数据。在这一过程中,我
L0bK4Vp
们发现了使用xml的很多有效方法。下面详细介绍我
L0bK4Vp
们现在的应用情况。
L0bK4Vp
L0bK4Vp
标准化
L0bK4Vp
在使用xml之前,建立与你要使用的信息不同的xml数据格式。
L0bK4Vp
L0bK4Vp
生成动态xml
L0bK4Vp
从数据库中生成html并不新鲜,但生成xml却很新鲜。这里我
L0bK4Vp
们介绍具体的生成步骤。
L0bK4Vp
L0bK4Vp
用xsl作为模板语言
L0bK4Vp
xsl(可扩展样式表语言)是定义xml数据显示格式的好方法,如果写成几个静态模板会更有效。
L0bK4Vp
L0bK4Vp
生成html
L0bK4Vp
xml加上xsl就等于html。这听起来似乎不对,但用户所见的我
L0bK4Vp
们的html页面其实就是xml和xsl共同产生的效果。
L0bK4Vp
L0bK4Vp
L0bK4Vp
一、标准化
L0bK4Vp
L0bK4Vp
xml的能力来自于它的灵活性。但不幸的是,它有时太灵活了,以至于你会面对一个空白的页面,发愁该怎么解决问题。
L0bK4Vp
L0bK4Vp
在任何xml的项目中,第一步工作都是创建标准的数据格式。为此你要作出以下决定:
L0bK4Vp
L0bK4Vp
• 要涉及哪些数据
L0bK4Vp
• 是否要使用dtd(文件类型定义)
L0bK4Vp
• 是否要使用dom(文档对象模型)或sax(xml的简化api)解析
L0bK4Vp
L0bK4Vp
确定数据:
L0bK4Vp
因为没有标准的xml格式,开发者可以自由地开发自己的格式。然而,如果你的格式只能被一个应用程序识别,那么你只能运行这个程序来使用该格式。如果还有其他程序也能读懂你的xml格式,那显然会更有帮助。如果某个xml格式被修改,则使用它的系统可能也需要被修改,所以你应该建立尽可能完整的格式。因为大多数系统忽略它们无法识别的标签,所以改变一个xml格式的最安全的方法是添加标签,而不是修改标签。
L0bK4Vp
L0bK4Vp
单击此处查看xml数据格式实例
L0bK4Vp
L0bK4Vp
在sparks.com,我
L0bK4Vp
们查看了不同的产品展示需要的所有产品数据。尽管并不是所有的页面都使用全部数据,但我
L0bK4Vp
们还是由此开发出适用于所有数据的非常完整的xml数据格式。例如,我
L0bK4Vp
们的产品明细信息页面显示的数据要比产品浏览页面多。然而,我
L0bK4Vp
们在这两种情况下仍然使用相同的数据格式,因为每个页面的xsl模板都只使用它所需要的字段。
L0bK4Vp
L0bK4Vp
是否使用dtd
L0bK4Vp
在sparks.com,我
L0bK4Vp
们使用组织良好的xml,而不使用仅仅是正确的xml,因为前者不需要dtd。dtd在用户点击和看到页面之间加入了一个处理层。我
L0bK4Vp
们发现这一层需要太多的处理。当然,在以xml格式与其他公司通信时,使用dtd还是很不错的。因为dtd能在发送和接受时能保证数据结构正确。
L0bK4Vp
L0bK4Vp
选择解析引擎
L0bK4Vp
现在,可以使用的解析引擎有好几个。选择哪一个几乎完全取决于你的应用需要。如果你决定使用dtd,那么这个解析引擎必须能使你的xml被dtd验证。你可以将验证另放到一个进程中,但那样会影响性能。
L0bK4Vp
L0bK4Vp
sax和dom是两个基本的解析模型。sax基于事件,所以在xml被解析时,事件被发送给引擎。接下来,事件与输出文件同步。dom解析引擎为动态xml数据和xsl样式表建立层次树状结构。通过随机访问dom树,可以提供xml数据,就象由xsl样式表来决定一样。sax模型上的争论主要集中于对dom结构的内存降低过度和加快xsl样式表解析时间缩短方面。
L0bK4Vp
L0bK4Vp
然而,我
L0bK4Vp
们发现使用sax的很多系统并没有充分发挥它的能力。这些系统用它来建立dom结构并通过dom结构来发送事件。用这种方法,在任何xml处理之前必须从样式表中建立dom,所以性能会下降。
L0bK4Vp
L0bK4Vp
二、生成动态xml
L0bK4Vp
L0bK4Vp
一旦建立了xml格式,我
L0bK4Vp
们需要一种能够将其从数据库中动态移植的方法。
L0bK4Vp
L0bK4Vp
生成xml文档相对来说比较简单,因为它只需要一个可以处理字符串的系统。我
L0bK4Vp
们建立了一个使用java servlet、enterprise javabean server、jdbc和rdbms(关系型数据库管理系统)的系统。
L0bK4Vp
L0bK4Vp
• servlet通过把生成xml文档的任务交给enterprise javabean (ejb)来处理产品信息请求。
L0bK4Vp
• ejb使用jdbc从数据库里查询所需的产品详细信息。
L0bK4Vp
• ejb生成xml文件并把它传递给servlet。
L0bK4Vp
• servlet调用解析引擎,从xml文件和静态的xsl样式表中创建html输出。
L0bK4Vp
L0bK4Vp
(有关xsl应用的其他信息,请参阅用xsl作为模板语言。)
L0bK4Vp
L0bK4Vp
生成xml的例子
L0bK4Vp
在java中创建xml文档字符串的真正代码可以分成几个方法和类。
L0bK4Vp
L0bK4Vp
启动xml生成过程的代码放在ejb方法里。这一实例会立即创建一个stringbuffer,以便存储生成的xml字符串。
L0bK4Vp
L0bK4Vp
stringbuffer xml = new stringbuffer();
L0bK4Vp
xml.append(xmlutils.begindocument("/browse_find/browse.xsl", "browse", request));
L0bK4Vp
xml.append(product.toxml());
L0bK4Vp
xml.append(xmlutils.enddocument("browse");
L0bK4Vp
out.print(xml.tostring());
L0bK4Vp
L0bK4Vp
L0bK4Vp
后面的三个xml.append()变元本身就是对其他方法的调用。
L0bK4Vp
产生文件头
L0bK4Vp
第一个附加方法调用xmlutils类来产生xml文件头。我
L0bK4Vp
们的java servlet中的代码如下:
L0bK4Vp
L0bK4Vp
public static string begindocument(string stylesheet, string page)
L0bK4Vp
{
L0bK4Vp
stringbuffer xml = new stringbuffer();
L0bK4Vp
xml.append("<?xml version=\"1.0\"?>\n")
L0bK4Vp
.append("<?xml-stylesheet href=\"")
L0bK4Vp
.append(stylesheet).append("\"")
L0bK4Vp
.append(" type =\"text/xsl\"?>\n");
L0bK4Vp
xml.append("<").append(page).append(">\n");
L0bK4Vp
return xml.tostring();
L0bK4Vp
}
L0bK4Vp
L0bK4Vp
这段代码生成了xml文件头。<?xml>标签把本文件定义为支持1.0版本的xml文件。第二行代码指向用以显示数据的正确样式表的位置。最后包括进去的是项级标签(本实例中为<browse>)。在文件末尾,只有<browse>标签需要被关闭。
L0bK4Vp
L0bK4Vp
<?xml version="1.0"?> <?xml-stylesheet href="/browse_find/browse.xsl" type="text/xsl"?> <browse>
L0bK4Vp
L0bK4Vp
填入产品信息
L0bK4Vp
完成了文件头后,控制方法会调用java对象来产生它的xml。本例中调用的是product对象。product对象使用两个方法来产生它的xml表示。第一个方法toxml()通过产生<product>和</product>标签来建立product节点。然后它会调用internalxml(),这样就能提供产品xml所需的内容。internalxml()是一系列的stringbuffer.append()调用。stringbuffer也被转换成字符串并返回给控制方法。
L0bK4Vp
public string toxml()
L0bK4Vp
{
L0bK4Vp
stringbuffer xml = new stringbuffer("<product>\n");
L0bK4Vp
xml.append(internalxml());
L0bK4Vp
xml.append("</product>\n");
L0bK4Vp
return xml.tostring();
L0bK4Vp
}
L0bK4Vp
L0bK4Vp
public string internalxml()
L0bK4Vp
{
L0bK4Vp
stringbuffer xml = new
L0bK4Vp
stringbuffer("\t")
L0bK4Vp
.append(producttype).append("\n");
L0bK4Vp
xml.append("\t").append(id&#118alue.trim())
L0bK4Vp
.append("\n");
L0bK4Vp
xml.append("\t").append(idname.trim())
L0bK4Vp
.append("\n");
L0bK4Vp
xml.append("\t").append(page.trim())
L0bK4Vp
.append("\n");
L0bK4Vp
厖?
L0bK4Vp
xml.append("\t").append(amount).append("\n");
L0bK4Vp
xml.append("\t").append(vendor).append("\n");
L0bK4Vp
xml.append("\t\n");
L0bK4Vp
xml.append("\t").append(pubdesc).append("\n");
L0bK4Vp
xml.append("\t").append(vendesc).append("\n";
L0bK4Vp
厖?
L0bK4Vp
return xml.tostring();
L0bK4Vp
}
L0bK4Vp
L0bK4Vp
L0bK4Vp
关闭文件
L0bK4Vp
最后,xmlutils.enddocument()方法被调用。这个调用关闭xml标签(本例中为),并最终完成架构好的xml文件。来自控制方法的整个stringbuffer也转换成字符串,并返回给处理最初http请求的servlet。
L0bK4Vp
L0bK4Vp
三、用xsl作为模板语言
L0bK4Vp
L0bK4Vp
为了得到html输出,我
L0bK4Vp
们把生成的xml文件和控制xml数据如何表示的xsl模板相结合。我
L0bK4Vp
们的xsl模板由精心组织的xsl和html标签组成。
L0bK4Vp
L0bK4Vp
开始建模板
L0bK4Vp
我
L0bK4Vp
们的xsl模板开始部分与下面这段代码类似。第一行代码为必需代码,将本文件定义为xsl样式表。xmlns:xsl=属性引用本文件所使用的xml名称空间,而version=属性则定义名称空间的版本号。在文件的末尾,我
L0bK4Vp
们关闭标签。
L0bK4Vp
L0bK4Vp
由<xsl:template>开始的第二行代码确定了xsl模板的模式。match属性是必需的,在这里指向xml标签<basketpage>。在我
L0bK4Vp
们的系统里,<basketpage>标签里包含<product> 标签,这使得xsl模板可以访问嵌在<product>标签内的产品信息。我
L0bK4Vp
们又一次必须在文件末尾关闭<xsl:template>标签。
L0bK4Vp
L0bK4Vp
接下来,我
L0bK4Vp
们来看一看组织良好的html。由于它将被xml解析引擎处理,所以必须符合组织良好的xml的所有规则。从本质上来讲,这意味着所有的开始标签必须有对应的结束标签。例如,通常不被结束的<p>标签,必须用</p>关闭。
L0bK4Vp
L0bK4Vp
L0bK4Vp
<xsl:stylesheet xmlns:xsl="
http://www.w3.org/1999/xsl/transform"
;
L0bK4Vp
version="1.0">
L0bK4Vp
<xsl:template match="basketpage">
L0bK4Vp
<html>
L0bK4Vp
<head>
L0bK4Vp
<title>shopping bag / adjust quantity</title>
L0bK4Vp
</head>
L0bK4Vp
<body bgcolor="#cccc99" bgproperties="fixed" link="#990000" vlink="#990000">
L0bK4Vp
L0bK4Vp
L0bK4Vp
?br> </xsl:template>
L0bK4Vp
</xsl:stylesheet>
L0bK4Vp
L0bK4Vp
L0bK4Vp
在模板的主体内,有很多xsl标签被用于为数据表示提供逻辑。下面解释两个常用的标签。
L0bK4Vp
choose
L0bK4Vp
<xsl:choose>标签类似于传统编程语言中if-then-else结构的开始部分。在xsl中,choose标签表示在代码进入的部分中,赋值将触发动作的发生。拥有赋值属性的<xsl:when>标签跟在choose标签后面。如果赋值是正确的,位于<xsl:when>的开始和结束标签之间的内容将被使用。如果赋值错误,就使用<xsl:otherwise>的开始和结束标签之间的内容。整个部分用</xsl:choose>来结束。
L0bK4Vp
L0bK4Vp
在这个例子里,when标签会为quantity标签检查xml。如果quantity标签里含有值为真的error属性,quantity标签将会显示列在下面的表格单元。如果属性的值不为真,xsl将会显示otherwise标签间的内容。在下面的实例里,如果error属性不真,则什么都不会被显示。
L0bK4Vp
L0bK4Vp
<xsl:choose>
L0bK4Vp
<xsl:when test="quantity[@error='true']">
L0bK4Vp
<td bgcolor="#ffffff"><img height="1" width="1" src="/Files/Images/0582717180550601.gif"/></td>
L0bK4Vp
<td valign="top" bgcolor="#ffffff" colspan="2"><font face="verdana, arial" size="1" color="#cc3300"><b>*not enough in stock. your quantity was adjusted accordingly.</b></font></td>
L0bK4Vp
</xsl:when>
L0bK4Vp
<xsl:otherwise>
L0bK4Vp
</xsl:otherwise>
L0bK4Vp
</xsl:choose>
L0bK4Vp
L0bK4Vp
L0bK4Vp
for-each
L0bK4Vp
<xsl:for-each>标签可以用来对相似xml数据的多种情况应用同一个样式表。对于我
L0bK4Vp
们来说,可以从数据库中取出一系列产品信息,并在web页上进行统一格式化。这里有一个例子:
L0bK4Vp
<xsl:for-each select="package">
L0bK4Vp
<xsl:apply-templates select="product"/>
L0bK4Vp
</xsl:for-each>
L0bK4Vp
L0bK4Vp
L0bK4Vp
for-each 循环在程序遇到标签时开始。这个循环将在程序遇到标签时结束。一旦这个循环运行,每次标签出现时都会应用这个模板。
L0bK4Vp
L0bK4Vp
四、生成html
L0bK4Vp
L0bK4Vp
将来的某一时刻,浏览器将会集成xml解析引擎。到那时,你可以直接向浏览器发送xml和xsl文件,而浏览器则根据样式表中列出的规则显示xml数据。不过,在此之前开发者们将不得不在他们服务器端的系统里创建解析功能。
L0bK4Vp
L0bK4Vp
在sparks.com,我
L0bK4Vp
们已经在java servlet里集成了一个xml解析器。这个解析器使用一种称为xslt (xsl transformation)的机制,按xsl标签的说明向xsl模板中添加xml数据。
L0bK4Vp
L0bK4Vp
当我
L0bK4Vp
们的java servlet处理http请求时,servlet检索动态生成的xml,然后xml被传给解析引擎。根据xml文件中的指令,解析引擎查找适当的xsl样式表。解析器通过dom结构创建html文件,然后这个文件再传送给发出http请求的用户。
L0bK4Vp
L0bK4Vp
如果你选择使用sax模型,解析器会通读xml源程序,为每个xml标签创建一个事件。事件与xml数据对应,并最终按xsl标签向样式表中插入数据。
81267
返回页面顶端
上一篇:
利用xmlserializer将对象串行化到xml
下一篇:
在 xsl/xslt 中实现随机排序
返回上一页
打印本文
加入收藏
页面最后更新时间:2010年3月10日