车东 chedong@netease.com Google XML接口的XSLT设计 车东 chedong@netease.com
摘要 XML/XSLT的一些基本概念 XSLT和传统编程语言的比较 Google XML接口的XSLT设计中遇到的问题
传统开发中的问题 程序员/UI设计师职责不清晰,重复劳动很多 开发:UI和程序的开发无法并发进行 测试:无法区分数据/界面样式的错误 开发 维护:测试/更新 程序员 UI设计
XML设计意图:协作/分工/重用 程序员(数据) 用户输入数据校验 后台数据的正确性 调用XSLT模板转换XML数据源输出 结果:一劳永逸 UI设计师(形式) 模板设计 结果:工作难度提高 需要将XSLT当成一种编程语言来学习,日常维护可以独立进行 开发 维护:调试/更新 程序员 UI设计 较高的学习成本 较高的学习成本
XML 格式“象”HTML 主要面向:B2B的数据交换 更适于机器间的数据交换/绑定
XSLT XSL: eXtensible Stylesheet Language XSLT: XSL Transformations 是一种将XML转换成其他格式文档的编程语言 XSLT使用XPath在XML文档中定位节点
XML/XSLT的处理模式 网易 XSLT google 用户 xml html XSLT转换过程
XSLT对XML数据源转换过程 XML解析 xml:parse XSLT转换器: xslt:Transformer XML序列化 xml:Serializer 样式表树 XML解析 xml:parse XSLT输入: xslt:Source XSLT输出: xslt:Result 结果文档 xml XML数据源 结果文档 html 结果文档 text 数据源树 结果树 转换过程
XML:开发/调试工具 共同遵守的标准/规范:W3C Sun-JAXP 数据格式:google.dtd UI设计师:了解XSLT语法和调试方法 编辑工具:文本编辑器/XMLSpy… XSLT调试/测试工具:IE6/XT 程序员:了解工具包的使用 XSLT转换引擎:xalan XML解析器:xerces
Google/网易服务结构 1. HTTP GET 2. HTTP GET Round-Robin DNS Load balancing asia.google.com 亚洲数据中心 3. XML www.google.com 美国数据中心 Servlet Engine Web Server 4. HTML
提问? 后面将通过与传统编程类比方式,简单介绍一下XSLT语言
XSLT中的变量引用 xml: <Tag attr=“AttrValue”> Tag Value </Tag> xsl: <xsl:value-of select=“Tag” /> “Tag Value” <xsl:value-of select=“Tag/@attr" /> “AttrValue”
流程控制 <xsl:for-each> <xsl:if> <xsl:choose> <xsl:when> <xsl:otherwise>
匹配过程: match=“TAG”代替 m/^@?$#/ <xsl:template match=“TAG"> <!--do transfer…--> … </xsl:template> If ($line =~ /^TAG/) { #do transfer… … } vs.
匹配过程的模块化:函数重用 apply-templates代替sub function () Tag1(…); sub Tag1 () { if ($line =~ /^Tag2/ ) {… Tag2(…); } sub Tag2 () { … <xsl:template match="/"> <xsl:apply-templates select=“Tag1"/> </xsl:template> <xsl:template match="Tag1"> <xsl:apply-templates select=“Tag2"/> <xsl:template match=“Tag2"> … vs.
内置函数 XPath Functions number last() number position() number count(node-set) node-set id(object) string local-name(node-set) string namespace-uri(node-set) string name(node-set) string string(object) string concat(string1, string2, [string3, [string4], ...]) boolean starts-with(string1, string2) …… XSLT Functions node-set document(object, node-set?) node-set key(keyname, object) string format-number(number, formatstring, [decimalformat]) node-set current() string unparsed-entity-uri(string) string generate-id(node-set) object system-property(string) boolean element-available(string) ……
模板文件的模块化:函数库重用 <xsl:include href=“sub_module.xsl”/> <?xml version="1.0" encoding="GB2312"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:include href="style.xsl"/> <xsl:include href="header.xsl"/> <xsl:include href="footer.xsl"/> <xsl:include href="results.xsl"/> <xsl:include href="nav.xsl"/> <xsl:include href="ad.xsl"/> <xsl:include href="searchbox.xsl"/> … </xsl:stylesheet>
提问? 后面将具体介绍Google XML接口XSLT的模板设计过程中遇到的一些问题
忘掉HTML(常犯的错误常与HTML习惯有关) 如何将<NextPage>LinkValue</Next> 转成:<a href=“LinkValue”>下一页</a> 忘掉HTML(常犯的错误常与HTML习惯有关) <a href>…</a>在XML中和其他标记没有区别,都是符合XML标准的标记 最后问题归结为<a></a>是一个新的标记,标记的属性需要引用变量 正确的方法:<a href=“?q={Tag}”>上一页</a> {Tag} 是一种简化的<xsl:value-of>引用
最后序列化输出不想escaping 数据源中的标引:<b> <b> XSLT的转换结果首先是一个符合XML树,只是最后序列化成xml,html,text形式的文本 <xsl:text disable-output-escaping="yes"> <xsl:text>
其他常犯错误 正确 错误 <img src=”image.gif” /> “/”前需要空格 错误 <img src=”image.gif”> <a href=“?i=2&j=3”> <script src=“aa.js”></script> XSLT有IF,但没有 IF THEN ELSE… 正确 <img src=”image.gif” /> <a href= “?i=2&j=3” > 否则会将“&j=3”当成一个符号转义 <script src=“aa.js”><br /></script> 如果没有<br />就会序列化成:<script src=“” />这在html中是错误的 用xsl:choose xsl:when
XSLT引擎本身的一些限制 很多XSLT工具包都是按照IANA的规范设计的。规范定义中不包含GBK,因此序列化以后部分字符成为“??” http://www.iana.org/assignments/character-sets XSLT没有string_replace(因为是流式解析过程) “<b>” => “<d>” 可以 “<b>” => “<abc>” 不可以 用自定义函数=>比较复杂,而且会影响开发者的分工协作
Google接口的不足之处 通过固定参数顺序解决:Param[0]=>q Param[1]=>start 需要在程序里预先将字符串encoding好 通过style解决: blockquote b {color:red} 需要自己通过PARAM[]重新构造 肯定不能用小写(防止和html冲突),但大写缩写让客户比较难懂 使用xml_no_dtd接口 传递的参数用Param[]定义,构造搜索框,下一页时引用不方便 没有一个url encoded的query字段 不支持用户指定标引,缺省已经用“<b>key</b>”标引好了 数据有冗余:前页和后页的URL其实没用:命名方式的演化 命名方式的变化:GSP=>Suggestion 没有必要包含DTD声明,否则很多XSLT引擎的缺省设置会再向服务器端发一次请求要google.dtd
性能优化:XSLT的编译结果缓存 一个很好的例子:http://www.onjava.com/lpt/a//onjava/excerpt/java_xslt_ch5/index.html 序列化输出 解析数据源 解析XSL模板 模板编译
通用性设计 模板中的URL尽量使用 <a href=“?param=value”>… 可以模板和程序页面的名称无关 程序员和UI设计师的工作尽可能互不影响
提问? 个人感受 谢谢! 理解新标准的设计意图,但不要指望用新标准解决所有问题; 新标准往往只是用来解决旧标准不擅长解决的问题; 实际问题的解决往往是通过传统方法和新方法结合起来实现的。 谢谢!