2008年7月3日星期四

XML_012:JAXB介绍

【JAXB】:Java Architecture for XML Binding。
下面这张图清楚地说明了JAXB的功能。

我们已经知道了JAXP这个处理XML的API,也知道了有一些很好的Parser供应商。但有一个事实无法回避:无论你使用哪个Parser供应商,你都需要知道太多的处理细节:document,element,attribute......拜托!我只是想把一个XML文档读出来,修改一下,再存回去,为啥我必须要知道这些有关XML处理的细节?
于是JAXB应运而生了。
“这意味着你不需要处理甚至不需要知道XML编程技巧(如SAX或DOM)就能在Java应用程序中充分利用XML的优势。其结果是结合了高度可移植Java代码和高度可移植的XML数据。其中这些代码可用来创建灵活、轻便的应用程序和WebService。”

参考文献
1.
http://java.sun.com/developer/technicalArticles/WebServices/jaxb/
2.
http://www.itisedu.com/phrase/200604181429065.html
3.
https://jaxb.dev.java.net/

XML_011:XML Parser 和 XML Processor 介绍

该来介绍一下XML Parser 和 XML Processor了。
1. DOM4j:
http://www.dom4j.org/ 最新版本 1.6.1,2005年5月发布。(Parser + Processor)
2. JDOM:
http://www.jdom.org/ 最新版本 1.1,2007年11月发布。(Parser + Processor)
3. Xerces 2:
http://xerces.apache.org/xerces2-j/ 最新版本2.9.1,2006年11月发布。(Parser)
4. Xalan:
http://xml.apache.org/xalan-j/ 最新版本2.7.1,2007年11月发布。(Processor)
究竟哪个好,哪个不好,我没有做过严格测试,不敢乱说,不过网上有一些评论文章可以参考,读完之后感觉大家都比较推崇DOM4j。
//TODO DOM4j使用说明。
//TODO JDOM使用说明。
//TODO Xerces 2使用说明。
//TODO Xalan使用说明。
//TODO 综合评比。

2008年7月2日星期三

XML_010:JAXP介绍(摘录+整理)

前一篇讲了很多有关XML的概念,对于开发人员来说肯定更关心如何使用XML。对于Java开发人员来说,答案不言自明:就是JAXP。
【JAXP】:Java API for XML Processing。
“The Java API for XML Processing, or JAXP for short, enables applications to parse and transform XML documents using an API that is independent of a particular XML processor implementation. JAXP also provides a pluggability feature which enables applications to easily switch between particular XML processor implementations.”(英文定义来自
https://jaxp.dev.java.net/1.4/index.html
这里不再翻译,相信大家都看得懂。简明扼要的说:“JAXP is an abstract layer over an XSLT processor and an XML parser.”
JAXP1.3.x已经被包含在J2SE 5.0中,目前JAXP最新版本是1.4.2,被包含在J2SE 6.0中。更多信息请访问:
https://jaxp.dev.java.net/1.4/index.html

有一个事实必须首先明确:JAXP 本身不提供语法分析功能!语法分析功能是由语法分析器供应商提供的,如DOM4J。
那为何还要使用JAXP?——因为它能以一种独立于语法分析器供应商的方式处理XML。
JAXP主要依赖的API有:DOM和SAX 。

【DOM】:Document Object Model,文档对象模型。
DOM是处理XML文档的标准编程接口。由W3C制定,更多信息请访问:
http://www.w3.org/DOM/
DOM 是以层次结构组织起来的节点,或信息片段的集合。开发者可以“基于树”的方式来查找或修改信息。需要注意的是,浏览之前,内存需要装入整个“树结构”文档。

【SAX】:Simple API for XML。
由于DOM需要读取整个文件并将它存储到“树结构”中,因而效率不高并且消耗资源。SAX提供一个“基于事件”的机制:允许正在读取文档时处理该文档从XML文件读取资料,从而避免了在采取操作之前需要等待装入整个文档的所有内容。SAX的缺点是由于SAX不存储数据,所以无法对数据进行更改,或者“返回”数据流中前面的数据。注意,没有类似W3C的官方组织维护SAX的标准,SAX的标准由XML社区维护,更多信息请访问:
http://www.saxproject.org/
以下面这个XML为例,让我们看看DOM和SAX是如何解析的。

<?xml version="1.0"?>
<samples>
<server>UNIX</server>
<monitor>color</monitor>
</samples>


DOM 解析器将生成一个“树结构”装入内存中。矩形框表示元素节点,椭圆形表示文本节点。

SAX 解析器将生成以下事件:
Start document
Start element (samples)
Characters (white space)
Start element (server)
Characters (UNIX)
End element (server)
Characters (white space)
Start element (monitor)
Characters (color)
End element (monitor)
Characters (white space)
End element (samples)

问题1:何时选择DOM?
1. 需要对数据本身修改(不是光修改结构,如果是那样可以使用XSLT)。
2. 需要作为XML输出。

问题2:何时选择
SAX?1. 大文件。
2. 如果只使用一小部分数据,使用SAX 将数据抽取出来再处理。注意,处理中如果需要引用已经处理过的信息,SAX无法完成。
3. 性能要求高。

问题3:能否同时使用DOM和SAX?
当然可以。可以使用DOM 来创建事件的SAX 流,可以使用SAX来创建DOM树。事实上,大多数解析器实际常常使用SAX来创建DOM 树!

问题4:如何让我写的代码独立于不同的Parser供应商(不用修改代码)?
1. 更改Parser供应商际意味着更改类工厂,因为所有SAXParser 和DocumentBuilder 实例都来自这些类工厂。通过设置Java 系统属性可以更改类工厂的实现,比如:
javax.xml.parsers.DocumentBuilderFactory=com.foo.ConcreteDocumentBuilder
javax.xml.parsers.SAXParserFactory=com.foo.ConcreteSAXParser
javax.xml.transform.TranformerFactory=com.foo.ConcreteTransformer
2. 如果系统属性中没有指定,JAXP将会在JRE的目录中查找lib/jaxp.properties属性文件。
3. 如果jaxp.properties不存在或者没有相应的值,那么JAXP将会使用JAR文件的服务提供体制来定位正确的子类。简单地说,你可以在jar文件的META-INF/services目录下新建一个名为javax.xml.transform.TransformerFactory的文件,这个文件中只有一行:com.foo.ConcreteTransformer就可以了。
4. 如果上面3步都没有找到任何具体的实现,JAXP将使用缺省的实现。具体来说,在J2SE 1.4中使用的是Crimson + Xalan-J, 在J2SE 1.5中使用的是Xerxes 2.7 + XSLT,详细信息请参考:
https://jaxp.dev.java.net/1.4/JAXP-FAQ.html

参考文献:
1. JAXP官方网站:
https://jaxp.dev.java.net/1.4/index.html
2. 《JAXP 专述》 作者:
http://www-128.ibm.com/developerworks/cn/xml/jaxp/index.html
3. 《理解 DOM》 作者:
http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84890
3. 《理解 SAX》 作者:
http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84979

XML_002:encoding属性里面的学问 (摘录+整理)

XML文档第一行一般是XML声明,虽然不是必须的,但还是建议包含这行声明。形式如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
其中standalone属性表示是否需要导入其它文件,这是一个优化选项,如果为“yes”,希望解析器会做一些优化处理。默认为“no”。
encoding属性是我们要谈论的重点,有两个问题必须予以面对:

问题1:哪些值可以作为encoding的属性值?
问题不难,但Google了一圈,竟然没有找到答案!

问题2:为什么要有这个属性?
嘿嘿,说到这个问题,那可就要从字符与编码的发展说起,内容很多很杂,如果你没耐心,还是去别处玩耍吧。

1. 字符与编码的发展
从计算机对多国语言的支持角度看,大致可以分为三个阶段:
阶段一:系统内码为ASCII
【ASCII】:American Standard Code for Information Interchange 美国标准信息交换标准码。
【ANSI】:American National Standard Institute 美国国家标准学会。
【ISO】:International Organization for Standardization 国际标准化组织。
ASCII由ANSI在1967年最终制定的,标准的单字节字符编码方案,用于基于文本的数据。被ISO定为国际标准,称为ISO 646标准。
ASCII使用指定的7位二进制数[0x00~0x7F]来表示128种可能的字符:所有的大写和小写字母,数字0~9、标点符号,以及在美式英语中使用的特殊控制字符。
此时计算机只支持美式英语,其它语言不能够在计算机上存储和显示。
代表系统:英文DOS。
阶段二:系统内码为ANSI编码(本地化)
ASCII是美国标准,它甚至不能满足其它英语国家的需要(如英镑符号£),何况亚洲国家。
于是人们开始扩展ASCII ,扩充使用 [0x80~0xFF]来表示各自国家的语言字符。其中ISO 8859系列就是欧洲语言的扩展字符集。比如:


  • ISO 8859-1 (Latin-1) 西欧语言

  • ISO 8859-2 (Latin-2) 中欧语言

  • ISO 8859-3 (Latin-3) 南欧语言

  • ISO 8859-4 (Latin-4) 北欧语言

  • ISO 8859-5 (Cyrillic) 斯拉夫语言

  • ISO 8859-6 (Arabic) 阿拉伯语

  • ISO 8859-7 (Greek) 希腊语

  • ISO 8859-8 (Hebrew) 希伯来语

亚洲国家同样扩充使用[0x80~0xFF],不过是用2个bytes来表示1个字符。比如:汉字 “中”在中文操作系统中,使用[0xD6,0xD0]这2个字节存储。依此类推,亚洲国家产生了各自的编码标准。这些使用2个bytes来代表1个字符的各种汉字延伸编码方式,统称为ANSI编码。比如:


  • GB2312,简体中文字符集的中国国家标准,在ANSI中的代码页(Code Page)是CP936,收录7445 个字符,包括6763个汉字和682个符号。GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。对于人名、古汉语等方面出现的罕用字,GB2312不能处理,这导致了后来GBK以及GB18030字符集的出现。

  • BIG5编码 繁体中文。

  • JIS编码 日文。

在简体中文系统下,ANSI编码代表GB2312编码,在日文操作系统下,ANSI编码代表JIS编码。
显然,不同ANSI编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段ANSI 编码的文本中。比如:我们无法做到在浏览器上正确显示一个同时包含中日韩美法德文字的网页(有些变态,呵呵)。
代表系统:中文DOS,中文Windows 95/98,日文Windows 95/98 。
阶段三:系统内码为UNICODE(国际化)
为了促进国际间信息交流,
Unicode Consortium制定了UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换和处理的要求。这下可真是太好了,可以正确显示同时包含中日韩美法德的网页了!想想,同样的道理,在Google上能用简体中文查到繁体中文,甚至日文的结果。
代表系统:Windows NT/2000/XP,Linux 。
为了有更直观的感受,我们来有必要了解一下在三个阶段中,字符串在内存中是如何存放的:
◆在ASCII阶段,1个字符用1个字节表示。比如,“Bob123” 在内存中为:
42 6F 62 31 32 33 00 分别对应 B o b 1 2 3 \0。
◆ 在ANSI 编码阶段,1个字符用1个字节或多个字节来表示。比如,“中文123”在中文Windows 95 内存中为7个字节,1个汉字占2个字节,1个英文和数字占1个字节:
D6 D0 CE C4 31 32 33 00 分别对应 中 文 1 2 3 \0。
◆在UNICODE阶段,每个字符用在UNICODE字符集中的序号表示。目前计算机一般使用2个字节来存放一个序号(DBCS:double-byte character set )。比如,字符串“中文123”在Windows 2000下,内存中实际存放的是5个序号,一共占10个字节:
2D 4E 87 65 31 00 32 00 33 00 00 00 分别对应 中 文 1 2 3 \0。
注意,在x86 CPU中,低字节在前。

2. 字符,字节,字符串
(1)字符:人们使用的记号,抽象意义上的一个符号。如'1','中','a','$','¥'等。对应于Java语言中的char类型 1个char=2个bytes,其值就是UNICODE 中的序号
(2)字节:计算机数据存储单元,一个8位的二进制数。如0x01, 0x45, 0xFA等。对应于Java语言中的byte类型。
(3)ANSI字符串:在内存中,如果“字符”是以 ANSI 编码形式存在的,1个字符可能使用1个或多个字节来表示,那么我们称这种字符串为ANSI 字符串或者多字节字符串。比如:"中文123"(占7个字节)。对应于Java语言中的byte[]类型。
(4)UNICODE字符串:在内存中,如果“字符”是以在UNICODE 中的序号存在的,那么我们称这种字符串为UNICODE 字符串。如"中文123"(占10个字节)。 对应于Java语言中的String类型。
由于不同ANSI 编码所规定的标准是不相同的,因此,对于一个给定的多字节字符串,我们必须知道它采用的是哪一种编码规则,才能够知道它包含了哪些“字符”。相当于在Java语言中,作“字节串→字符串的转换” string = new String(bytes, "encoding")。而对于一个给定的UNICODE 字符串来说,不管在什么环境下,它所代表的“字符”内容总是不变的,至于“字符”内容所对应的字节有几个,是哪些字节,取决于你按哪种编码规则转换。相当于在Java语言中,作“字符串→字节串”的转换,bytes = string.getBytes("encoding")。
3. 字符集与编码(1)字符集:所包含“字符”的集合。比如“UNICODE 字符集”包含了各种语言中使用到的所有“字符”。
(2)编码:规定每个“字符”分别用1个字节还是多个字节存储,用哪些字节来存储,这个规则叫做“编码”。比如:常见的UNICODE 字符集编码有UTF-8,UTF-16。

4. UTF-8 编码原理


【UTF】:Unicode Transformation Format 通用字集变换格式,推荐使用UTF-8和UTF-16。其中8和16指的是bits,不是bytes。
【UTF-16】:基本上就是Unicode的双bytes编码的实现,再加上一个应付未来扩充需要的编码机制。
【UTF-8】:一种不等幅的编码方式。英文不需要转换,其他语言则需要转换,而且会变“胖”,因为每个字符需要多用1到2个bytes来编码。

UTF-8共有三种可能的编排方式,各自需要用到1、2、3个bytes,所以说它是不等幅。从下图我们可以看出:
1. U+0000~U+007F 用单byte表示所有的ASCII,且第一个bit是0,所以所有的ASCII码都不需要转换,就是自然相对的UTF-8码;反过来说,只要不是ASCII码,在UTF-8就需要2个或2个以上的bytes来编码表示。
2. U+0080~U+07FF
3. U+0800~U+FFFF

UTF-8三种形式中提供的自由bits(蓝色小方块)数,刚刚好对应该区位中的各个Unicode码。
那么当程序处理UTF-8编码的文件时,如何得知它到底是哪一种形式呢?
答案是上图中的绿色小方块。每个以UTF-8编码的字符,第1个byte的前端都表明了该字符的byte总数。而且每个多重byte的UTF-8编码的共性是,其第2个或第3个byte,一律以10这两个bits打头,很容易和只用到一个byte的ASCII码区分开来。
我们知道汉字“你”的Unicode是0x4F60,据此我们可以推导出它的UTF-8码是E4 BD A0。推导过程如下:
0x4F60的二进制如下:
0100 1111 0110 0000
用UTF-8第3种方式补齐,变成:1110 0100 1011 1101 1010 0000,于是得到E4 BD A0。


很显然,使用UTF-8编码会使中、日、韩文变胖,变成原来的150%(针对GB2312而言)。如果使用UTF-16编码,虽然不会增加亚洲文字的空间,但对于西文来说,等于增加了一倍,变成原来的200%,显然更不好,毕竟,是目前在网络上还是英文占主导地位。所以从这一点来说,UTF-8优点还是大于缺点。


参考文献:
1. 《无废话 XML》 作者:劳虎。
2.
http://www.unicode.org/
3.
http://www.xikao.com/reference/unicode.htm
4.
http://www.chedong.com/tech/hello_unicode.html
5.
http://www-128.ibm.com/developerworks/cn/java/java_chinese/index.html
6.
http://www-128.ibm.com/developerworks/cn/java/l-javachinese/index.html
7.
http://www.cn-java.com/www1/?action-viewnews-itemid-210
8.
http://www.regexlab.com/zh/encoding.htm
9.
http://epasser.aydc.com.cn/article/adp/2/content15103.html
10.
http://www.builder.com.cn/2007/1118/640102.shtml
11.
http://bbs.chinaunix.net/viewthread.php?tid=666899
12.
http://blog.csdn.net/liujin4049/archive/2007/04/10/1559576.aspx
13.
http://book.xker.com/others/web/web/jsp/index3/10.htm

2008年7月1日星期二

XML_001:XML是个啥东东?

要说XML,必须从HTML说起。
【HTML】:HyperText Markup Language,超文本标记语言。
“HTML是为网页创建和其它可在网页浏览器中看到的信息设计的一种置标语言。HTML被用来结构化信息——例如标题、段落和列表等等,也可用来在一定程度上描述文档的外观和语义。”(摘自http://zh.wikipedia.org/wiki/HTML
HTML的最新版本是4.0.1,由W3C在1999年12月制定,规范详细内容请访问:http://www.w3.org/TR/html4/

不难发现,HTML的缺陷就在它自己的定义中:描述文档的外观。HTML中有很多标签可以对布局和外观有很好的掌控,但对内容本身却缺乏表达能力。
比如说HTML可以用多种方式(列表、表格)的方式显示出一个订单,而却无法知道哪个信息是产品名称,哪个是产品价格,也就是说HTML中没有一个标签是用来描述产品名称和产品价格的。
于是,一些人开始思考:开发网页时,能不能把信息的展现方式和信息内容本身分开来呢?
答案当然是肯定的,它就是XHTML+CSS。

【XHTML】:eXtensible HyperText Markup Language,可扩展超文本标记语言。
XHTML与HTML类似,不过语法上更加严格。
XHTML的最新版本是1.1,由W3C在2007年2月制定,规范详细内容请访问:http://www.w3.org/TR/xhtml11/
强烈建议使用XHTML 1.1进行网页开发。
XHTML与HTML 的区别主要有以下4点:
1. 元素和属性的名称一律用小写字母。
2. 所有的元素必须要正确关闭。空标签的自闭方法如下:在标签的“>”符号前加上一个空格和一个反斜杠“/”。例如 <hr />。
3. 元素之间的嵌套关系一定要正确。
4. 属性值必须要用双引号“"”引起来。

如何验证网页是否符合XHTML1.1的严格标准:
http://www.w3school.com.cn/xhtml/xhtml_validate.asp
输入网页地址即可验证,我用我的blog试了一下,竟然有119 Errors, 96 warning(s) 。天啊,难道我的blog这样不守规矩吗?

常见错误提示:
1. required attribute X not specified:元素中缺少必须的属性。
2. end tag for X omitted, but OMITTAG NO was specified:元素没有关闭。
3. XML Parsing Error:
(1)Opening and ending tag mismatch:元素开闭标签不匹配。
(2)特殊符号如:<、>、&未用编码表示。

【CSS】:Cascading Style Sheets,层叠样式表。
“CSS是一种用来为结构化文档(HTML或XML)添加样式(字体、间距和颜色等)的计算机语言。”(摘自http://zh.wikipedia.org/wiki/CSS
CSS的最新版本是2.1,由W3C在2007年7月制定,规范详细内容请访问:http://www.w3.org/TR/CSS21/

【XML】:Extensible Markup Language,可扩展标记语言。
与XHTML使用国际通用的标记不同,XML可以使用人们自由决定的标记,这就是其语言的可扩展性。
XML的最新版本是1.0,由W3C在2006年9月制定,规范详细内容请访问:http://www.w3.org/TR/xml/
每个人都可以自由地制定自己的标记语言,不用再遵守大公司的条条框框,这是多么了不起的想法。实际上,许多行业已经有了自己的标记语言。比如:
CML:Chemistry Markup Language
MathML:Mathematical Markup Language

【XML Schema】
XML Schema 是一种描述XML文档结构语言。XML Schema本身也是一份XML文档,其XML名称空间为http://www.w3.org/2001/XMLSchema
XML Schema的最新版本是1.1,由W3C在2008年6月制定,规范详细内容请访问:http://www.w3.org/XML/Schema

【XPath】:XML Path Language,XML路径语言。
XPath是一种用来确定XML文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。
XPath的最新版本是2.0,由W3C在2007年1月制定,规范详细内容请访问:http://www.w3.org/TR/xpath20/

【XQuery】:XML Query Language,XML查询语言。
“解释XQuery 的最佳方式是:XQuery 相对于XML,等同于SQL 相对于数据库。”(摘自http://www.w3school.com.cn/xquery/index.asp
XQuery的最新版本是1.0,由W3C在2007年1月制定,规范详细内容请访问:http://www.w3.org/TR/xquery/

XPath与XQuery相同与不同:
“XPath 和XQuery 都能实现一些相同的功能,但是XPath比较简洁而XQuery更加强大和灵活。对于很多查询来说XPath 非常合适。
比如,从XML文档中的部分记录建立电话号码的无序列表,使用XPath实现最简单。
但是如果需要表达更复杂的记录选择条件的表达式、转换结果集或者进行递归查询,则需要使用XQuery。” (摘自http://www.ibm.com/developerworks/cn/xml/x-xqueryxpath.html

【XSLT】:Extensible Stylesheet Language Transformations,扩展样式表转换语言。
XSLT是把XML文档转化为另一文档的转换语言(利用XPath选择源文档的数据或者部分数据)。
它是XSL规范的一部分。XSLT是声明性的语言,本身只包含了一些转换规则的文档。这些规则可以被递归地应用到转换过程中。
XSLT本身也是一份XML文档,其XML名称空间为http://www.w3.org/1999/XSL/Transform
XSLT的最新版本是2.0,由W3C在2007年1月制定,规范详细内容请访问:http://www.w3.org/TR/xslt20/

名词解释:
1. 【W3C】:World Wide Web Consortium
万维网联盟为解决Web应用中不同平台、技术和开发者带来的不兼容问题,制定了一系列标准,其中包括XMLCSS等众多影响深远的标准规范。关于W3C更多信息请访问:http://www.w3.org/

参考文献:
1. 《无废话 XML》 作者:劳虎。
2. 《XML 教程》 作者:http://www.w3school.com.cn/xml/
3. 《XML Schema 教程》 作者:http://www.w3school.com.cn/schema/index.asp
4. 《XPath 教程》 作者:http://www.w3school.com.cn/xpath/index.asp
5. 《XQuery 教程》 作者:http://www.w3school.com.cn/xquery/index.asp
6. 《XSLT 教程》 作者:http://www.w3school.com.cn/xsl/index.asp
7. 《XQuery对XPath的扩展 》 作者:http://www.ibm.com/developerworks/cn/xml/x-xqueryxpath.html