??xml version="1.0" encoding="utf-8" standalone="yes"?>
作?Jimmy Zhang;rainy14f(作者的blog:http://shaofan.blogjava.net/)
概要
VTD-XML改变了游?/span>
资源
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=933706
做ؓ下一代WEB应用的推动性技术,XML相当单,易学易用。然而,当前的XML处理技术却非如此。Document Object Model和Simple API for XML都比较慢Q低效,且不易于使用。VTD-XMLQ作Z一代的XML处理模型Q提供超DOM和SAX的广泛用途和更佳选择Q不仅可以简化XML~程Q也佉K择XML处理模型更加Ҏ。这文章通过最q的基准试数据和示例程序来H显它的关键性的技术优势,昄出VTD-XML可能解决长期以来困C业架构的Q在DOM和SAX之间q行抉择的问题?br />
自从诞生以来的八q里QXML作ؓ一个开放,半结构化的数据格式和WEB应用的数据交换工P已取得了长q步。由于它的简易性和良好的可L,XML受到开发h员的热烈Ƣ迎Qƈ且已l成Z企业架构不可分割的一部分?br />
虽然很难说清XML到底有多种不同的应用,但至有一Ҏ肯定的:XML解析处理已成为各U工作的先决d。实际上Q决定用哪U解析器也经常是企业开发者在目中必首先解决的问题之一。长久以来,q其实就是在两种 XML处理模型之间做出选择QDocument Object Model (DOM) ?Simple API for XML (SAX)?br />
_看之下QDOM和SAX各自的优~点刚好形成互补。DOM使用内存保存对象l构Q而SAX则基于事件ƈ且不使用内存来存储Q何数据。因此,DOM比较适合文档较小而数据访问模式复杂的情况Q相反情况下Q则使用SAX?br />
然而事实却q不q么单纯。很多情况下Q开发者不情愿使用复杂的SAXQ但又不得不用,因ؓ没有其他选择。此外,即XML文g的大只是稍微大于几百KQDOM的内存开销和性能q滞也会成ؓ手的障,使得E序无法辑ֈ目所要求的最低性能目标?br />
那么是否SAX的性能真得好得多?实际上,SAX所吹嘘的解析性能――通常比DOM快几倍――常常是不现实的。事实显C,SAXW拙的,只能往前的解析不仅在用时相当不便Q而且当文档结构稍微复杂时Q也会遇到性能问题。如果开发h员不惛_ơ扫描文档,那么需要对文档q行~冲Q或构徏自己的对象模型?br />
不管使用哪种ҎQ性能都会成ؓ问题Q正如Apache Axis所证明的那栗在Axis的FAQ面Q它声称使用了SAX来构建高性能的实玎ͼ但它仍然使用了他们自q和DOM非常相像的对象模型。但与它的前?(Apache SOAP) 相比Q这U做法ƈ没有带来明显的性能提升。而且QSAX无法处理XPathQ一般来说也无法驱动XSLT (Extensible Stylesheet Language Transformation) 的处理。因此,SAX仍然无法真正解决XML处理中的问题?br />
ZL一个更易用的SAX的取代方案,来多的开发h员开使{向StAX (Streaming API for XML)。与SAX相比QStAX使用从XML文g中提取标记的ҎQ而不是回调。这U方案显著地改善了可用性,但一个基本的问题仍然存在――StAX的只能往前的解析对于E序员依然不便,而且存在隐藏的性能损失?br />
底线是:M惛_到广泛应用的XML处理模型Q必需能够完整体现XML的层ơ结构。这是因为,XML是被设计为在WEB上传输复杂数据的Q因此完整展现它的结构信息也是它的Q务之一?/p>
假设我们要从头开始一个XML处理q程Qƈ克服上面提到的DOM和SAX的种U缺点,那么q个新的模型应该h以下属性:
* 随机讉K能力Q处理模型应该允许开发h员方便访问文档的某种层次l构Q比如,使用XPathQ或手动?br />* 高性能Q性能上与DOM及SAX相比Q应有显著提高,而且q个“性能”应该是真实的,是_应该把徏立文档层ơ结构的旉也算上?br />* 低内存占用率Q要使该模型能够被广泛应用于各种场景Q不文件的大小Q那它就必须能够以最低的内存消耗来表现XML的结构?br />
VTD-XML是一个实Cq些目标的下一代的开源XML处理模型。它相比于DOM和SAX有着本质和全面的改进。VTD-XML的一个关键优化是非提取符?non-extractive tokenization)。在其内部,VTD-XML在内存中保存完整及未解码的XML消息Qƈ使用一个二q制~码规范来唯一地表C每个符受这U规范被UCؓVirtual Token DescriptorQ虚拟符hq符Q。每个VTD记录都是一?4字节的整敎ͼ它对XML中符L长度Qv始偏U量Q类型,嵌套深度q行了编码?br />
再简单地介绍一下VTD-XML的历Ԍ也许你会感兴:最初这个概忉|被用来在特定g讑֤上用,以ɘq些gQ如路由器,交换机)可以高速处理XMLQ比如FPGA,ASIC。此后,VTD-XML目l决定它开源,q于2004q五月发布了VTD-XML的最初版本,0.5版,用JAVA实现。从那时赗VTD-XMLl历了多ơ改qƈ来成熟。在0.8版本中,C语言版本的VTD-XML与JAVA版同时发布。在1.0版中引入了对XPath的内建支持,?005q?0月发布。最新的版本?.5版,它的解析引擎被重新编写以实现更强的模块化和更高的性能?br />
同样Q在q个版本中还出现了一个新的特性,叫作~冲重用。它的基本概忉|Q当XML应用需要通过|络q接来反复地dXML文档Ӟ该应用会重用在第一ơ处理中分配的内存缓册Ӏ换句话_即一ơ分配,多次使用。就VTD-XML来讲Q这个特性完全消除了在处理XMLq程中徏立对象和垃圾回收的开销Q在DOM和SAX中占?0%?0%的开销Q。在该项目的|站上,提供有最新的软g下蝲和深层技术说明?br />
一个简短例?/span>
Z使你更好C解VTD-XML~程的风|本文首先对用VTD-XML和DOM解析和访问一个简单的XML文gq行Ҏ。该文g名ؓtest.xmlQ内容如下:<purchaseOrder orderDate="1999-10-21">
<item partNum="872-AA">
<productName>Lawnmower</productName>
<quantity>1</quantity>
<USPrice>148.95</USPrice>
</item>
</purchaseOrder>
VTD-XML版本的程序如下:import com.ximpleware.*;
import com.ximpleware.parser.*;
import java.io.*;
public class use_vtd {
public static void main(String[] args){
try{
File f = new File("test.xml");
FileInputStream fis = new FileInputStream(f);
byte[] ba = new byte[(int)f.length()];
fis.read(ba);
VTDGen vg = new VTDGen();
vg.setDoc(ba);
vg.parse(false);
VTDNav vn = vg.getNav();
if (vn.matchElement("purchaseOrder")){
System.out.println(" orderDate==>"
+ vn.toString(vn.getAttrVal("orderDate")));
if (vn.toElement(VTDNav.FIRST_CHILD,"item")){
if (vn.toElement(VTDNav.FIRST_CHILD)){
do {
System.out.print( vn.toString(vn.getCurrentIndex()));
System.out.print("==>");
System.out.println( vn.toString(vn.getText()));
} while(vn.toElement(VTDNav.NEXT_SIBLING));
}
}
}
}
catch (Exception e){
System.out.println("exception occurred ==>"+e);
}
}
}
实现同样功能的DOM版本的程序:import java.io.*;
import org.w3c.dom.*;
import org.w3c.*;
import javax.xml.parsers.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
public class use_dom {
public static void main(String[] args){
try{
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document d= parser.parse("test.xml");
Element root = d.getDocumentElement();
if (root.getNodeName().compareTo("purchaseOrder")==0){
System.out.println(" orderDate==> "
+ root.getAttribute("orderDate"));
Node n = root.getFirstChild();
if (n != null){
do {
if (n.getNodeType() == Node.ELEMENT_NODE
&& n.getNodeName().compareTo("item")==0){
Node n2 = n.getFirstChild();
if (n2!=null){
do {
if (n2.getNodeType()
== Node.ELEMENT_NODE){
System.out.println(
n2.getNodeName()
+ "==>" +
n2.getFirstChild().getNodeValue()
);
}
}while((n2=n2.getNextSibling())!=null);
}
}
}while ((n=n.getNextSibling()) != null );
}
}
}
catch (Exception e){
System.out.println("exception occurred ==>"+e);
}
}
}
像以上所展示的那PVTD-XML使用Z游标的API来访问XML层次l构。相比之下,DOM API通过h对象的引用来达成同样目标。VTD-XML的项目网站提供更多详l的技术资料和CZE序?br />
VTD-XML的基准测?/span>
下面Q我们来比较一下VTD-XML一些流行的XML解析器的性能和内存占用情c值得注意的是Q多数包含基准测试数据的文章Q如Dennis Sosnoski?002q?月发表在JavaWorld上的“XML Documents on the Run”,都是多年前的文章。自那以后,如摩定律所C,更好更快的硬件大量涌现ƈ来便宜。同ӞXML解析与JVM技术也q未止步不前――在一些关键领域做Z改进?br />
试讄
试q_是Sony VAIOW记本电脑,使用Pentium M 1.7 GHz处理器(2MB L2 cacheQ,512MB DDR2内存。前端ȝ频率?00MHz。操作系lؓWindows XP Professional Edition with Services pack 2。JVM版本?.5.0_06?br />对以下XML解析器的最新版本进行了基准试Q?br />*Xerces DOM 2.7.1, 带有及不带有延迟节点扩展(deferred node expansion)
*Xerces SAX 2.7.1
*Piccolo SAX 1.04
*XPP3 1.1.3.4.O
*VTD-XML 1.5, 带有及不带有~冲重用
在测试中我用了大量不同大小和不同复杂程度的XML文档。从文档大小上,我把它们分ؓ三类Q小文gQ小?0KBQ;中文Ӟ10KB?MBQ;大文Ӟ大于1MBQ?br />在全部的性能度量中我都用了服务器的JVM来获取最高性能。在q些试中,基准试E序首先会多ơ解析或讉K文档QJVM对字节码q行x动态优化,之后才取得性能的^均g为最l结果。ؓ了减由于磁盘IOD的时间差别,基准试E序在测试运行之前已l把XML文gd到内存中?br />
注意Q有兴趣的读者可以从资源下蝲基准试E序?br />
吞吐量对比解?/strong>
本节在gq时间和吞吐量上对XML解析性能q行描述。要注意的是VTD-XML与DOM可直接进行比较,而与SAX或Pull直接Ҏ很不公qI因ؓ它们不在内存中构ZQ何层ơ结构。因此SAX和Pull的性能在此只作为额外参考?br />吞吐?br />
?1. 文?
?2. 中文?
?3. 大文?
延迟旉Ҏ
?1. 文?br />
?2. 中文?br />
?3. 大文?br />
内存占用率对?br />因ؓSAX和Pull不在内存中构ZQ何数据结构,所以这Ҏ试只有与DOM的对比才有意义。因此,本节对倍加pL(multiplying factor)q行衡量Q该pL为内存占用率与大文g的文件大之比(内存占用对大文g特别重要Q?br />
?4.
讉K性能Ҏ
本节从gq时间上展示VTD-XML与DOM 的访问性能。gq时间是指访问文档中每个节点所q旉。ؓ了遍历所有节点,DOM依赖于nodeInterator接口Q而VTD-XML则调用AutoPilotcȝ成员ҎselectElement(?与iterate(?。如所预期的一P讉K速度比解析速度要快得多。对VTD-XMLQ访问时间开销在解析时间开销?5%?0%之间。对DOMQ该数字?%?%。这q不说明VTD-XML的访问速度慢于DOM。这完全是因为VTD-XML有着非常快的解析速度?br />
?4. 文?br />
?5. 中文?br />
?6. 大文?br />
l果分析
在Dennis Sosnoski四年前发表于JavaWorld的文章中QPiccolo是众多SAX实现中的赢家。现在这得到了改变:最新的Xerces击|众多Ҏ成ؓ性能最好的SAX解析器。测试结果也昄Q与Xerces相比QXPP3也有相当不错的性能Q不比前者相差很多?br />另外Q有的是,当文件较时QDOM与SAX的解析性能差距q不像在解析大文件时的相差那么大。在文件的情况下,DOM的gq节Ҏ展导致比使用完全节点扩展要差的解析性能?br />
而VTD-XML的出众性能使它完全胜过其他M解析器,q它自成一U。真正的比较只是存在于用缓冲重用的VTD-XML及不使用~冲重用的VTD-XML之间。内存占用率上的重大优势使得VTD-XML可以被用于处理大XML文档Qƈ且对L大小的文仉有较好的性能?br />
l论
VTD-XML是一U全新的Q下一代的XML解析器。它解决了许多目前困扰DOM和SAX的问题。VTD-XML高性能与低内存占用的结合意味着Q首先,DRAM已经相当便宜Q如果不是完全没有空间存放XML文档Q那没有多理׃用SAXQ其ơ,使用VTD-XML使得应用变得更加单,更快。它对各U大的文g的适应性,使得选择一个合适的XML处理模型变得单,而开发h员也不必再在完全不同的DOM和SAX中进行切换了Q最后,VTD-XML可以为长久以来对XML的不满提供一个oZ服的{案。比如,VTD-XML内徏了本地XML索引的能力,也许可以怹改变认ؓXML速度慢的看法。正׃它的性能优势QVTD-XML应该标志着?0倍速XML”时代的到来。更重要的是QVTD-XML的下一站,只在咫尺之遥Q那是?00倍速XML”?/p>
*VTD-XML:http://vtd-xml.sf.net/
*Apache Axis FAQ:http://ws.apache.org/axis/faq.html#faq1
*下蝲基准试E序:http://sourceforge.net/project/showfiles.php?group_id=110612
]]>
SAXBuilder sb = new SAXBuilder();
try
{
Document doc = sb.build(path);
Element root = doc.getRootElement();
Element subroot=root.getChild("entity");
Element content=subroot.getChild("contents");
List entities=content.getChildren("entity");
for(int j=0;j<entities.size();j++)
{
Element _element=(Element)entities.get(j);
if(_element.getChild("nick").getText().equals(catalog))
{
System.out.println(_element.getChild("nick").getText());
System.out.println(_element.getChild("description").getText());
content.removeContent(_element);
//_element.removeContent(_element);
}
}
Format format = Format.getCompactFormat();
format.setEncoding("UTF-8"); //讄xml文g的字WؓUTF-8
format.setIndent(" "); //讄xml文g的羃qؓ4个空?/em>
XMLOutputter xmlOutput = new XMLOutputter(format);
xmlOutput.output(root, new FileOutputStream(path));
}
catch(Exception e)
{
e.printStackTrace();
}
}
XML文g片:
<entity>
<description>文档目录理</description>
<imageBase>images/globe.gif</imageBase>
<imageOpen>images/globe_selected.gif</imageOpen>
<contents>
<entity>
<nick>1</nick>
<description>档案理E序</description>
<imageBase>images/book.gif</imageBase>
<imageOpen>images/bookOpen.gif</imageOpen>
<contents>
<entity>
<nick>1</nick>
<description>国家Linux技术培训与推广中心档案查询登记?lt;/description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心档案查询登记?lt;/title>
<dir>doc/1/1.doc</dir>
</entity>
<entity>
<nick>2</nick>
<description>国家Linux技术培训与推广中心档案理E序</description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心档案理E序</title>
<dir>doc/1/2.doc</dir>
</entity>
<entity>
<nick>3</nick>
<description>lnic人员理办法</description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>lnic人员理办法</title>
<dir>doc/1/3.txt</dir>
</entity>
</contents>
</entity>
<entity>
<nick>2</nick>
<description>对外业务</description>
<imageBase>images/book.gif</imageBase>
<imageOpen>images/bookOpen.gif</imageOpen>
<contents>
<entity>
<nick>1</nick>
<description>国家Linux技术培训与推广中心供应商调查报?lt;/description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心供应商调查报?lt;/title>
<dir>doc/2/1.doc</dir>
</entity>
<entity>
<nick>2</nick>
<description>国家Linux技术培训与推广中心国有资甌?lt;/description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心国有资甌?lt;/title>
<dir>doc/2/2.doc</dir>
</entity>
<entity>
<nick>3</nick>
<description>国家Linux技术培训与推广中心合格供应商名?lt;/description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心合格供应商名?lt;/title>
<dir>doc/2/3.doc</dir>
</entity>
<entity>
<nick>4</nick>
<description>国家Linux技术培训与推广中心q货质量验收计划</description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心q货质量验收计划</title>
<dir>doc/2/4.doc</dir>
</entity>
<entity>
<nick>5</nick>
<description>国家Linux技术培训与推广中心培训协议?lt;/description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心培训协议?lt;/title>
<dir>doc/2/5.doc</dir>
</entity>
<entity>
<nick>6</nick>
<description>国家Linux技术培训与推广中心外购物品验收报告</description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>国家Linux技术培训与推广中心外购物品验收报告</title>
<dir>doc/2/6.doc</dir>
</entity>
<entity>
<nick>7</nick>
<description>lnic人员器材理办法</description>
<imageBase>images/paper.gif</imageBase>
<imageOpen>images/paper.gif</imageOpen>
<title>lnic人员器材理办法</title>
<dir>doc/2/7.doc</dir>
</entity>
</contents>
</entity>
错误出现在: 1?font color="#ff1493">content.removeContent(_element);
2?font color="#ffa500"> //_element.removeContent(_element);
用第2U方法总达不到效果Q搞了半天才更正了错误?/font>
解决ҎQ?br />1.指定输出文档cd为xml文档 (example:data.xsl)
<xsl:output method=xml encoding=gb2312 media-type=text/xml />
2.在新的窗口打开Q给联接增加属?指明目标H口为其他窗口?(example:data2.xsl)
<xsl:attribute name=target>_blank</xsl:attribute>
examples:
/*** data.xml ***/
<?xml version=1.0 encoding=gb2312?>
<?xml-stylesheet type=text/xsl href=data.xsl?>
<root>
<search>
<url>http://www.google.com/search?q=</url>
<word>xml数据</word>
</search>
<search>
<url>http://www1.baidu.com/baidu?word=</url>
<word>xml数据</word>
</search>
<search>
<url>http://www.google.com/search?q=</url>
<word>极限~程(xp)</word>
</search>
<search>
<url>http://www1.baidu.com/baidu?word=</url>
<word>极限~程(xp)</word>
</search>
</root>
/*** data.xsl ***/
<?xml version=1.0 encoding=gb2312?>
<xsl:stylesheet version=1.0 xmlns:xsl=http://www.w3.org/1999/XSL/Transform>
<!-- L下面一?出现错?-->
<xsl:output method=xml encoding=gb2312 media-type=text/xml />
<xsl:template match=/>
<xsl:apply-templates />
</xsl:template>
<xsl:template match=search>
<xsl:element name=a>
<xsl:attribute name=href><xsl:value-of select=url /><xsl:value-of select=word /></xsl:attribute>
<xsl:value-of select=word />
</xsl:element>
<br />
</xsl:template>
</xsl:stylesheet>
/*** data2.xsl ***/
<?xml version=1.0 encoding=gb2312?>
<xsl:stylesheet version=1.0 xmlns:xsl=http://www.w3.org/1999/XSL/Transform>
<xsl:template match=/>
<xsl:apply-templates />
</xsl:template>
<xsl:template match=search>
<xsl:element name=a>
<xsl:attribute name=href><xsl:value-of select=url /><xsl:value-of select=word /></xsl:attribute>
<!-- L下面一?出现错?-->
<xsl:attribute name=target>_blank</xsl:attribute>
<xsl:value-of select=word />
</xsl:element>
<br />
</xsl:template>
</xsl:stylesheet>