XML技术在界面生成中的简单应用(XSLT相关)1
首先,请确认如下概念您都有一定的了解,当然,如果您并没有相应的基础,这里列出了一些基本概念和W3C相应教程的链接。
XML
XML 指可扩展标记语言,其被设计用来传输和存储数据。
XSL
XSL 指扩展样式表语言(EXtensible Stylesheet Language),其作用一定程度上相当于HTML中的CSS,但它不仅仅是一种样式表语言,而是包含了如下三部分:
XSLT
XSLT 指 XSL 转换。 既是将 XML 文档通过 XSL 转换为其他文档,比如 XHTML。
XPath
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 同时被构建于 XPath 表达之上。
XML Schema
XML Schema 用于描述 XML 文档的结构,XML Schema 语言也称作 XML Schema 定义(XML Schema Definition,XSD)。
接下来应该对上面所提到的技术或多或少有了一些了解了吧?那么就说一下我接下来想要做些什么练习题吧!哦,对了,我还用到了Bootstrap,谁让咱美工不太好呢。
先看看东西效果。然后再清理一下思绪。接着在着手做出类似的东西来巩固下。
界面是不怎么样,不过咱不也不只是为了看个界面吗,就是为了知道要做个什么东西出来。不过这可不是最终目标哦!只是其中一个课题。当然,就算到了最后,我也不能够把我的整个项目都拿出来给大家,但是还是会很乐意给出一些自己的见解与大家一起分享,把一些做项目中做得小功课拿出来跟大家分享。
首先,先整理下这些知识点:
在XML中引用一个XSLT样式表
1 <!-- 在XML中引入一个XSLT样式表--> 2 <?xml-stylesheet type="text/xsl" href="xslt/catalog.xslt"?>
在一个XSLT文件中引用一个外部XSLT文件
<!-- 在一个XSLT文件中引用一个外部XSLT文件 --> <xsl:import href="path/file.xslt" />
输出符合HTML5 标准的HTML代码
1 <!-- 输出符合HTML5 标准的HTML代码 --> 2 <?xml version="1.0" encoding="utf-8"?> 3 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 4 5 <xsl:output method="html" indent="yes" /> 6 7 <!-- 将Page替换为XML根节点,即可作为XSLT入口 --> 8 <xsl:template match="/Page"> 9 <!-- 输出符合HTML5规范的DOCTYPE --> 10 <xsl:text disable-output-escaping='yes'><!DOCTYPE html></xsl:text> 11 <html lang="zh-cn"> 12 <head> 13 <meta charset="utf-8" /> 14 <title> 15 <xsl:value-of select="@Title"/> 16 </title> 17 <link href="css/bootstrap.min.css" rel="stylesheet" /> 18 <link href="css/bootstrap-responsive.min.css" rel="stylesheet" /> 19 <script src="js/jquery-1.7.1.min.js"></script> 20 <script src="js/bootstrap.min.js"></script> 21 </head> 22 <body> 23 <!-- 根据XML节点自动应用符合条件的模板 --> 24 <xsl:apply-templates select="*"></xsl:apply-templates> 25 </body> 26 </html> 27 </xsl:template> 28 29 </xsl:stylesheet>
匹配当前节点的 XSLT 模板
1 <!-- 匹配当前节点的 XSLT 模板 --> 2 <xsl:template match="//TextField"> 3 </xsl:template>
命名的XSLT模板以及如何调用命名的XSLT模板
<!-- 命名的XSLT模板 --> <xsl:template name="named-template"> </xsl:template> <!-- 调用命名的XSLT模板 --> <xsl:call-template name="named-template"></xsl:call-template>
整理上面提到的知识点时,就不得不对XSLT的模板多加思考下,于是就想,如果一个空间的表现、数据绑定、交互都能有它们的定义,我们能仅仅只是组合这些定义,具体的操作事先已经被封装到XSLT的模板里面,那该多好呢!
哦!想法不错,那如果基础不牢固怎么办呢?先做第一个功课,来巩固一下XSLT相关的知识好吗?顺便也多想想现有方案的缺点,一起找出更好的解决方案。于是,我做了如下设想:
呵呵,XSD能想到怎么定义了吗?要不我把我的先拿上来吧,不过临时定义的,逻辑很不严谨。而且结构也非常不好。不过又说回来了,我上来就哪个完美的,接下来还学习什么呢?就啃它吗?
1 <?xml version="1.0" encoding="utf-8"?> 2 <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 3 <xs:element name="Page"> 4 <xs:complexType> 5 <xs:sequence> 6 <xs:element ref="Container"></xs:element> 7 </xs:sequence> 8 <xs:attribute name="Title" type="xs:string" use="required" /> 9 </xs:complexType> 10 </xs:element> 11 <xs:element name="Container"> 12 <xs:complexType> 13 <xs:sequence> 14 <xs:element ref="Form"></xs:element> 15 </xs:sequence> 16 <xs:attribute name="fluid" type="xs:boolean" use="required" /> 17 </xs:complexType> 18 </xs:element> 19 <xs:element name="Form"> 20 <xs:complexType> 21 <xs:sequence> 22 <xs:element maxOccurs="unbounded" ref="Group"></xs:element> 23 <xs:element ref="Row"></xs:element> 24 </xs:sequence> 25 <xs:attribute name="Layout" type="xs:string" use="required" /> 26 <xs:attribute name="Title" type="xs:string" use="required" /> 27 </xs:complexType> 28 </xs:element> 29 <xs:element name="Group"> 30 <xs:complexType> 31 <xs:sequence> 32 <xs:element maxOccurs="unbounded" ref="Row"></xs:element> 33 </xs:sequence> 34 <xs:attribute name="Title" type="xs:string" use="required" /> 35 </xs:complexType> 36 </xs:element> 37 <xs:element name="Row"> 38 <xs:complexType> 39 <xs:sequence> 40 <xs:element maxOccurs="unbounded" ref="Cell"></xs:element> 41 </xs:sequence> 42 </xs:complexType> 43 </xs:element> 44 <xs:element name="Cell"> 45 <xs:complexType> 46 <xs:sequence> 47 <xs:element minOccurs="0" ref="OptionGroup"></xs:element> 48 <xs:element minOccurs="0" ref="Dropdown"></xs:element> 49 <xs:element minOccurs="0" ref="TextField"></xs:element> 50 <xs:element ref="Actions"></xs:element> 51 </xs:sequence> 52 <xs:attribute name="Cols" type="xs:unsignedByte" use="required" /> 53 </xs:complexType> 54 </xs:element> 55 <xs:element name="Option"> 56 <xs:complexType> 57 <xs:attribute name="Multy" type="xs:boolean" use="required" /> 58 <xs:attribute name="Label" type="xs:string" use="required" /> 59 <xs:attribute name="GroupName" type="xs:string" use="required" /> 60 </xs:complexType> 61 </xs:element> 62 <xs:element name="OptionGroup"> 63 <xs:complexType> 64 <xs:sequence> 65 <xs:element maxOccurs="unbounded" ref="Option"></xs:element> 66 </xs:sequence> 67 <xs:attribute name="Title" type="xs:string" use="required" /> 68 </xs:complexType> 69 </xs:element> 70 <xs:element name="Dropdown"> 71 <xs:complexType> 72 <xs:sequence> 73 <xs:element maxOccurs="unbounded" name="Option"> 74 <xs:complexType> 75 <xs:attribute name="Text" type="xs:string" use="required" /> 76 <xs:attribute name="Value" type="xs:unsignedByte" use="required" /> 77 </xs:complexType> 78 </xs:element> 79 </xs:sequence> 80 <xs:attribute name="Label" type="xs:string" use="required" /> 81 <xs:attribute name="Caption" type="xs:string" use="required" /> 82 <xs:attribute name="Cols" type="xs:unsignedByte" use="required" /> 83 <xs:attribute name="Multy" type="xs:boolean" use="required" /> 84 </xs:complexType> 85 </xs:element> 86 <xs:element name="TextField"> 87 <xs:complexType> 88 <xs:attribute name="Label" type="xs:string" use="required" /> 89 <xs:attribute name="Cols" type="xs:unsignedByte" use="required" /> 90 </xs:complexType> 91 </xs:element> 92 <xs:element name="Actions"> 93 <xs:complexType> 94 <xs:sequence> 95 <xs:element maxOccurs="unbounded" ref="Action"></xs:element> 96 </xs:sequence> 97 </xs:complexType> 98 </xs:element> 99 <xs:element name="Action"> 100 <xs:complexType> 101 <xs:attribute name="Caption" type="xs:string" use="required" /> 102 </xs:complexType> 103 </xs:element> 104 </xs:schema>
接下来给出个思路和代码,比如Form:
Form出现在什么位置不是我们所能确定的,但是我们可以要求用XML表达的时候一定用Form节点。
Form里面出现的内容我们也不能规定死,因为我们可能不仅仅想放表单元素,甚至还想放些东西布局是不,虽然说XSD定义的并不支持那么多,但是哪个XSD也只是我临时定义的,而且结构不合理。之后我要有时间会尽量多花些时间定义些相对好些的XSD。
好了,思路有了, 实现也不会难到那里去吧! Form位置的不确定性和XML中规定使用Form节点表示正好表达了要我们使用一个匹配当前Form节点的模板,别忘了还有个Title,至于Action什么的现在都先不考虑,现在只管呈现! Form里面不管放了什么内容, 都先给它呈现吧!像这样是不?
1 <xsl:template match="//Form"> 2 <form> 3 <fieldset> 4 <legend> 5 <xsl:value-of select="@Title"/> 6 </legend> 7 8 <xsl:apply-templates select="*"></xsl:apply-templates> 9 10 </fieldset> 11 </form> 12 </xsl:template>
也许你会觉得Form这种东西本来就比较简单, 再加上去掉了Method,ACTion等东西,也就不用什么逻辑就写出来了。拿在看个有点逻辑的吧。 单选框组好不?那里面东西稍多些。其实不也就是一个标签, 加上一堆单选输入组件吗。只要name相同,就实现了单选了, 哦,复选也差不多哦。就放一起了。挺晚了,我还是少说点,直接上代码,您稍稍看看也就明白了。因为这次说的本来就是简单的东西的。
1 <xsl:template match="//OptionGroup"> 2 <div class="control-group"> 3 <xsl:if test="string-length(@Title) > 0"> 4 <label class="control-label"> 5 <xsl:value-of select="@Title"/> 6 </label> 7 </xsl:if> 8 <div class="controls"> 9 <xsl:for-each select="Option"> 10 <xsl:call-template name="option-template"> 11 <xsl:with-param name="groupName" select="@GroupName"></xsl:with-param> 12 </xsl:call-template> 13 </xsl:for-each> 14 </div> 15 </div> 16 </xsl:template> 17 18 <xsl:template name="option-template"> 19 <xsl:param name="groupName"></xsl:param> 20 <xsl:if test="@Multy != 'true'"> 21 <label class="radio inline"> 22 <input type="radio"> 23 <!--<xsl:if test="$groupName">--> 24 <xsl:attribute name="name"> 25 <xsl:value-of select="$groupName"/> 26 </xsl:attribute> 27 <!--</xsl:if>--> 28 <xsl:if test="@Selected"> 29 <xsl:attribute name="checked"> 30 <xsl:value-of select="'checked'"/> 31 </xsl:attribute> 32 </xsl:if> 33 </input> 34 <xsl:value-of select="@Label"></xsl:value-of> 35 </label> 36 </xsl:if> 37 <xsl:if test="@Multy = 'true'"> 38 <label class="checkbox inline"> 39 <input type="checkbox"> 40 <xsl:if test="@Selected"> 41 <xsl:attribute name="checked"> 42 <xsl:value-of select="'checked'"/> 43 </xsl:attribute> 44 </xsl:if> 45 </input> 46 <xsl:value-of select="@Label"></xsl:value-of> 47 </label> 48 </xsl:if> 49 </xsl:template>
简单不?哦,数据绑定还没加呢。先不考虑SEO吧。因为我做这个的目的是考虑AJAX项目快速开发的。当然,做非AJAX的会更加舒适,因为可以直接拿来XML当数据啊。让后XSLT转换啊。不过操作都在客户端的AJAX项目也不用太愁,谁让那么多有智慧又有爱心的人已经给我们准备好了那么多好用的Javascript库呢。
先看看这个KnockoutJS (教程 | 文档)怎么样,要不您找个更好的也行,反正也就一类库,就算自己写,只要功能能实现,足够稳定都是可以的,不是吗?