﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-梦在飞-文章分类-XML</title><link>http://www.blogjava.net/vso/category/16172.html</link><description>JAVA EE</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:57:05 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:57:05 GMT</pubDate><ttl>60</ttl><item><title>用JDOM包实现生成XML文件的简单示例</title><link>http://www.blogjava.net/vso/articles/74813.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 08:55:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74813.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74813.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74813.html</trackback:ping><description><![CDATA[
		<blockquote>
				<font color="#000000" size="4">CODE: 
<hr /></font>
				<pre>
						<font color="#000000" size="4">
								<br />import java.io.*;<br />import org.jdom.*;<br />import org.jdom.input.*;<br />import org.jdom.input.*;<br />import org.jdom.output.*;<br /><br />public class test1 {<br />    public void BuildXMLDoc() throws IOException, JDOMException {<br />        Element eeeRoot, eee1, eee2;<br />        Document Doc;<br />        eeeRoot = new Element("employees_information");<br />        Doc = new Document(eeeRoot);<br />        eeeRoot = Doc.getRootElement();<br /><br />        eee1 = new Element("name");<br />        eee2 = eee1.setText("C.Y. Shen");<br />        //eee2 = eee1.addAttribute("emp_id", "001");<br />        eee1 = eeeRoot.addContent(eee2);<br /><br />        eee1 = new Element("age");<br />        eee2 = eee1.setText("43");<br />        eee1 = eeeRoot.addContent(eee2);<br /><br />        eee1 = new Element("sex");<br />        eee2 = eee1.setText("Male");<br />        eee1 = eeeRoot.addContent(eee2);<br />        XMLOut.setEncoding("gb2312") ； XMLOutputter XMLOut = new XMLOutputter();<br />        XMLOut.output(Doc, new FileOutputStream("test1.xml"));<br />    }<br /><br />    public static void main(String[] args) {<br />        try {<br />            test1 s1 = new test1();<br />            System.out.println("Now we build an XML document .....");<br />            s1.BuildXMLDoc();<br />        } catch (Exception e) {<br />            System.out.println(e.getMessage());<br />        }<br />    }<br />}<br /></font>
				</pre>
				<font color="#000000" size="4">
						<hr />
				</font>
		</blockquote>
		<br />
		<br />输出如下：<br />&lt;?xml version="1.0" encoding="gb2312" ?&gt; <br />- &lt;employees_information&gt; <br />&lt;record&gt;<br />&lt;name&gt;C.Y. Shen&lt;/name&gt; <br />&lt;age&gt;43&lt;/age&gt; <br />&lt;sex&gt;Male&lt;/sex&gt; <br />&lt;/employees_information&gt;<img src ="http://www.blogjava.net/vso/aggbug/74813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 16:55 <a href="http://www.blogjava.net/vso/articles/74813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过XSLT访问Java代码[转]</title><link>http://www.blogjava.net/vso/articles/74812.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 08:53:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74812.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74812.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74812.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74812.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74812.html</trackback:ping><description><![CDATA[假如你希望将XML数据转换为固定宽度和纯文本的字符串——这刚好是XSLT不太方便实现的一个特性，或者，也许你希望在XML文件中执行词语替换。在这些情况下，当你的事务超出了XSLT自身的处理能力时，可以通过在你的XSLT处理器中调用Java函数来完成。<br />我看到过利用类似VBScript和Jscript的脚本语言完成特殊处理的例子（针对微软解析器的），但是如何利用Java来执行特殊的处理还不是特别地明显。尽管如此，简单地说，可以在XSLT处理器中通过XML命名空间（namespaces）调用Java函数来实现。Java与XSLT的结合为构建健壮的应用程序提供了强有力的方法。<br />使用定制的命名空间<br />命名空间是通过使用统一资源标识符(URI)来修饰限定XSL中元素和属性名称的一种方法。例如，常见的XSL元素需要有xsl命名空间前缀来修饰，xsl通过使用XSLT命名空间URI来声明：<br />xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <br />但是并不局限于使用XSLT命名空间，你完全可以自由地声明你自己定制的命名空间，并用它们来识别定制的XSLT标签和范围。<br />你必须使用定制的命名空间前缀来完成对外部函数的调用，例如，mynspace:fundtion()，该命名空间前缀mynspace，必须与一个命名空间URI相关联，例如：<br />xmlns:myspace="d:///XMLprogs/mynamespace" <br />一般的Java绑定使用命名空间URI标识Java类函数的位置。对用于本文示例代码的Xalan XSLT处理器（版本1.2.2）来说，命名空间URI必须具有URI-stem/packagename的形式。如果你使用了XT，那么你的命名空间应该有如下格式：<br />xmlns:mynspace="d://XMLprogs/mynamespace.myclassname <br />这种情况下，你可以使用XSLT代码调用来自myclassname的Java函数。<br />绑定外部Java函数<br />此处给出在XSLT模板内部绑定Java语言编写的外部函数的过程。<br />将你自己定制的命名空间作为它们的属性添加到样式表（stylesheet）元素或者你的模板中。<br />确保你的Java类文件所在目录位于你的XSLT处理器所运行的Java虚拟机（JVM）的CLASSPATH中。<br />对于静态方法，可以使可以用完全合格的类名称加上方法和任何必需的的参数，当然还有命名空间前缀。<br />对于非静态方法，首先创建类实例，然后调用该方法并提供任何必需的参数。<br />例如，下面的样式表元素包含一个定制的命名空间声明：<br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;?xml version=”1.0” encoding=”UTF-8”?&gt;<br />&lt;xsl:stylesheet version=”1.0” xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” xmlns:myspace=”d://XMLprogs/mynamespace”&gt; <br /></pre><hr /></blockquote><br />在声明了这个命名空间后，可以访问该类的任何静态方法，像这样：<br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;xsl:variable name=”funvalue”select=”mynspace:classname.function()”/&gt; <br /></pre><hr /></blockquote><br />如果方法不是静态的，那么必须首先调用类构造器，例如：<br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;xsl:variable name="funvalue" select="mynspace.classname.new()"/&gt;<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="d://XMLprogs/mynamespace" exclude-result-prefixes="java"&gt; <br /></pre><hr /></blockquote><br />Java包\"mynamespace"必须位于"d://XMLprogs"目录中。<br />注意：使用可选属性xsl:exclude-result-prefixes，预防了java命名空间被包括到结果文档中。<br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;xsl:template match="/"&gt;<br />&lt;html&gt;<br />&lt;body&gt;<br />&lt;p&gt;<br />&lt;xsl:value-of select="java:DateClass.displayDate()"/&gt;<br />&lt;/p&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br />&lt;/xsl:template&gt; <br /></pre><hr /></blockquote><br />上面的XSLT代码中，&lt;xsl:value-of select="java:DateClass.displayDate()"/&gt;行调用位于mynamespace包中名为DateClass的类的静态方法displayDate()。<br />利用这种技术，你可以调用任何Java类方法——包括那些需要参数的方法——参数来自于你的XSLT模板。<br />本文涉及的代码：date.xsl<br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:java="d://XMLprogs/mynamespace" exclude-result-prefixes="java"&gt;<br />&lt;xsl:template match="/"&gt;<br />&lt;html&gt;<br />&lt;body&gt;<br />&lt;p&gt;<br />&lt;xsl:value-ofselect="java:DateClass.displayDate()" /&gt;<br />&lt;/p&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br />&lt;/xsl:template&gt;<br />&lt;/xsl:stylesheet&gt;<br />DateClass.java<br />packagemynamespace;<br />importjava.util.Date;<br />public class DateClass{<br />public static String displayDate(){<br />Date d = new Date();<br />returnd.toString();<br />}<br />} <br /></pre><hr /></blockquote><br />要运行这些代码，需要：<br />创建文件夹"d:XMLProgsmynamespace"。<br />将DateClass.java文件放入上述路径并编译得到DateClass.class文件。<br />将"d:XMLProgsmynamespace"放入classpath变量中。<br />利用XSLT处理器，例如XT或XALAN将该XSL文件和具体的XML文件关联。 <img src ="http://www.blogjava.net/vso/aggbug/74812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 16:53 <a href="http://www.blogjava.net/vso/articles/74812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java与XML联合编程之SAX篇</title><link>http://www.blogjava.net/vso/articles/74811.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74811.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74811.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74811.html</trackback:ping><description><![CDATA[SAX概念 <br />SAX是Simple API for XML的缩写，它并不是由W3C官方所提出的标准，可以说是“民间”的事实标准。实际上，它是一种社区性质的讨论产物。虽然如此，在XML中对SAX的应用丝毫不比DOM少，几乎所有的XML解析器都会支持它。 <br /><br />与DOM比较而言，SAX是一种轻量型的方法。我们知道，在处理DOM的时候，我们需要读入整个的XML文档，然后在内存中创建DOM树，生成DOM树上的每个Node对象。当文档比较小的时候，这不会造成什么问题，但是一旦文档大起来，处理DOM就会变得相当费时费力。特别是其对于内存的需求，也将是成倍的增长，以至于在某些应用中使用DOM是一件很不划算的事（比如在applet中）。这时候，一个较好的替代解决方法就是SAX。 <br /><br />SAX在概念上与DOM完全不同。首先，不同于DOM的文档驱动，它是事件驱动的，也就是说，它并不需要读入整个文档，而文档的读入过程也就是SAX的解析过程。所谓事件驱动，是指一种基于回调（callback）机制的程序运行方法。（如果你对Java新的代理事件模型比较清楚的话，就会很容易理解这种机制了） <br /><br /><a href="http://www0.ccidnet.com/tech/guide/2001/10/08/image/image006.gif" target="_blank"><img title="open in new window" alt="" src="http://www0.ccidnet.com/tech/guide/2001/10/08/image/image006.gif" border="0" /></a><br />在XMLReader接受XML文档，在读入XML文档的过程中就进行解析，也就是说读入文档的过程和解析的过程是同时进行的，这和DOM区别很大。解析开始之前，需要向XMLReader注册一个ContentHandler，也就是相当于一个事件监听器，在ContentHandler中定义了很多方法，比如startDocument()，它定制了当在解析过程中，遇到文档开始时应该处理的事情。当XMLReader读到合适的内容，就会抛出相应的事件，并把这个事件的处理权代理给ContentHandler，调用其相应的方法进行响应。 <br /><br />这样泛泛的说来或许有些不容易理解，别急，后面的例子会让你明白SAX的解析过程。看看这个简单XML文件： <br /><br />&lt;POEM&gt;<br />&lt;AUTHOR&gt;Ogden Nash&lt;/AUTHOR&gt;<br />&lt;TITLE&gt;Fleas&lt;/TITLE&gt;<br />&lt;LINE&gt;Adam&lt;/LINE&gt;<br />&lt;/POEM&gt; <br /><br />当XMLReader读到&lt;POEM&gt;标签时，就会调用ContentHandler.startElement()方法，并把标签名POEM作为参数传递过去。在你实现的startElement()方法中需要做相应的动作，以处理当&lt;POEM&gt;出现时应该做的事情。各个事件随着解析的过程（也就是文档读入的过程）一个个顺序的被抛出，相应的方法也会被顺序的调用，最后，当解析完成，方法都被调用后，对文档的处理也就完成了。下面的这个表，列出了在解析上面的那个XML文件的时候，顺序被调用的方法： <br /><br /><a href="http://download.cnjsp.org/images/cnjsp_doc_image_20031219_02.gif" target="_blank"><img title="open in new window" alt="" src="http://download.cnjsp.org/images/cnjsp_doc_image_20031219_02.gif" border="0" /></a><br />ContentHandler实际上是一个接口，当处理特定的XML文件的时候，就需要为其创建一个实现了ContentHandler的类来处理特定的事件，可以说，这个实际上就是SAX处理XML文件的核心。下面我们来看看定义在其中的一些方法： <br /><br />void characters(char[] ch, int start, int length)： <br /><br />这个方法用来处理在XML文件中读到字符串，它的参数是一个字符数组，以及读到的这个字符串在这个数组中的起始位置和长度，我们可以很容易的用String类的一个构造方法来获得这个字符串的String类：String charEncontered=new String(ch,start,length)。 <br /><br />void startDocument()： <br /><br />当遇到文档的开头的时候，调用这个方法，可以在其中做一些预处理的工作。 <br /><br />void endDocument()： <br /><br />和上面的方法相对应，当文档结束的时候，调用这个方法，可以在其中做一些善后的工作。 <br /><br />void startElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName, Attributes atts) <br /><br />当读到一个开始标签的时候，会触发这个方法。在SAX1.0版本中并不支持名域，而在新的2.0版本中提供了对名域的支持，这儿参数中的namespaceURI就是名域，localName是标签名，qName是标签的修饰前缀，当没有使用名域的时候，这两个参数都未null。而atts是这个标签所包含的属性列表。通过atts，可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理，在遇到一个标签的时候，它并不会纪录下以前所碰到的标签，也就是说，在startElement()方法中，所有你所知道的信息，就是标签的名字和属性，至于标签的嵌套结构，上层标签的名字，是否有子元属等等其它与结构相关的信息，都是不得而知的，都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。 <br /><br />void endElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName) <br /><br />这个方法和上面的方法相对应，在遇到结束标签的时候，调用这个方法。 <br /><br />因为ContentHandler是一个接口，在使用的时候可能会有些不方便，因而，SAX中还为其制定了一个Helper类：DefaultHandler，它实现了这个接口，但是其所有的方法体都为空，在实现的时候，你只需要继承这个类，然后重载相应的方法即可。 <br /><br />OK，到这儿SAX的基本知识已经差不多讲完了，下面我们来看看两个具体的例子，以更好的理解SAX地用法。 <br /><br />SAX编程实例 <br />我们还是沿用讲DOM的时候使用的那个文档例子，但首先，我们先看一个简单一些的应用，我们希望能够统计一下XML文件中各个标签出现的次数。这个例子很简单，但是足以阐述SAX编程的基本思路了。 <br /><br />一开始当然还是import语句了： <br /><br />import org.xml.sax.helpers.DefaultHandler;<br />import javax.xml.parsers.*;<br />import org.xml.sax.*;<br />import org.xml.sax.helpers.*;<br />import java.util.*;<br />import java.io.*; <br /><br />然后，我们创建一个继承于DefaultHandler的类，具体的程序逻辑在这儿可以暂且放在一边，要注意的是程序的结构： <br /><br />public class SAXCounter extends DefaultHandler {<br />private Hashtable tags; //这个Hashtable用来记录tag出现的次数<br />// 处理文档前的工作\<br />public void startDocument() throws SAXException {<br />tags = new Hashtable();//初始化Hashtable<br />}<br />//对每一个开始元属进行处理\<br />public void startElement(String namespaceURI, String localName,<br />String rawName, Attributes atts)<br />throws SAXException<br />{<br />String key = localName;<br />Object value = tags.get(key);<br />if (value == null) {<br />// 如果是新碰到的标签，这在Hastable中添加一条记录<br />tags.put(key, new Integer(1));<br />} else {<br />// 如果以前碰到过，得到其计数值，并加1<br />int count = ((Integer)value).intValue();<br />count++;<br />tags.put(key, new Integer(count));<br />}<br />}<br />//解析完成后的统计工作\<br />public void endDocument() throws SAXException {<br />Enumeration e = tags.keys();<br />while (e.hasMoreElements()) {<br />String tag = (String)e.nextElement();<br />int count = ((Integer)tags.get(tag)).intValue();<br />System.out.println("Tag &lt;" + tag + "&gt; occurs " + count<br />+ " times");<br />}<br />}<br />//程序入口，用来完成解析工作\<br />static public void main(String[] args) {<br />String filename = null;<br />boolean validation = false;<br />filename="links.xml";<br />SAXParserFactory spf = SAXParserFactory.newInstance();<br />XMLReader xmlReader = null;<br />SAXParser saxParser=null;<br />try {<br />// 创建一个解析器SAXParser对象\<br />saxParser = spf.newSAXParser();<br />// 得到SAXParser中封装的SAX XMLReader<br />xmlReader = saxParser.getXMLReader();<br />} catch (Exception ex) {<br />System.err.println(ex);<br />System.exit(1);<br />}<br />try {<br />//使用指定的ContentHandler，解析给XML文件，这儿要注意的是，为了<br />//程序的简单起见，这儿将主程序和ContentHandler放在了一起。实际上<br />//main方法中所作的所有事情，都与ContentHandler无关。<br />xmlReader.parse(new File(filename),new SAXCounter());<br />} catch (SAXException se) {<br />System.err.println(se.getMessage());<br />System.exit(1);<br />} catch (IOException ioe) {<br />System.err.println(ioe);<br />System.exit(1);<br />}<br />}<br />} <br /><br />我们来看看这段程序作了些什么，在main()方法中，主要做的就是创建解析器，然后解析文档。实际上，在这儿创建SAXParser对象的时候，为了使程序代码于具体的解析器无关，使用了同DOM中一样的设计技巧：通过一个SAXParserFactory类来创建具体的SAXParser对象，这样，当需要使用不同的解析器的时候，要改变的，只是一个环境变量的值，而程序的代码可以保持不变。这就是FactoryMethod模式的思想。在这儿不再具体讲了，如果还有不明白的，可以参看上面DOM中的解释，原理是一样的。 <br /><br />不过在这儿还有一点点要注意的地方，就是SAXParser类和XMLReader类之间的关系。你可能有些迷糊了吧，实际上SAXParser是JAXP中对XMLReader的一个封装类，而XMLReader是定义在SAX2.0种的一个用来解析文档的接口。你可以同样的调用SAXParser或者XMLReader中的parser()方法来解析文档，效果是完全一样的。不过在SAXParser中的parser()方法接受更多的参数，可以对不同的XML文档数据源进行解析，因而使用起来要比XMLReader要方便一些。 <br /><br />这个例子仅仅涉及了SAX的一点皮毛，而下面的这个，可就要高级一些了。下面我们要实现的功能，在DOM的例子中已经有实现了，就是从XML文档中读出内容并格式化输出，虽然程序逻辑看起来还是很简单，但是SAX可不比DOM哦，看着吧。 <br /><br />前面说过，当遇到一个开始标签的时候，在startElement()方法中，我们并不能够得到这个标签在XML文档中所处的位置。这在处理XML文档的时候是个大麻烦，因为在XML中标签的语义，有一部分是由其所处的位置所决定的。而且在一些需要验证文档结构的程序中，这更是一个问题。当然，没有解决不了的问题了，我们可以使用一个栈来实现对文档结构的纪录。 <br /><br />栈的特点是先进先出，我们现在的想法是，在startElemnt()方法中用push将这个标签的名字添加到栈中，在endElement()方法中在把它pop出来。我们知道对一个结构良好的XML而言，其嵌套结构是完备的，每一个开始标签总会对应一个结束标签，而且不会出现标签嵌套之间的错位。因而，每一次startElement()方法的调用，必然会对应一个endElement()方法的调用，这样push和pop也是成对出现的，我们只需要分析栈的结构，就可以很容易的知道当前标签所处在文档结构中的位置了。 <br /><br />public class SAXReader extends DefaultHandler {<br />java.util.Stack tags=new java.util.Stack();<br />//--------------XML Content-------------<br />String text=null;<br />String url=null;<br />String author=null;<br />String description=null;<br />String day=null;<br />String year=null;<br />String month=null;<br />//----------------------------------------------<br />public void endDocument() throws SAXException {<br />System.out.println("------Parse End--------");<br />}<br />public void startDocument() throws SAXException {<br />System.out.println("------Parse Begin--------");<br />}<br />public void startElement(String p0, String p1, String p2, Attributes p3) throws SAXException {<br />tags.push(p1);<br />}<br />public void endElement(String p0, String p1, String p2) throws SAXException {<br />tags.pop();<br />//一个link节点的信息收集齐了，将其格式化输出\<br />if (p1.equals("link")) printout();<br />}<br />public void characters(char[] p0, int p1, int p2) throws SAXException {<br />//从栈中得到当前节点的信息<br />String tag=(String) tags.peek();<br />if (tag.equals("text")) text=new String(p0,p1,p2);<br />else if (tag.equals("url")) url=new String(p0,p1,p2);<br />else if (tag.equals("author")) author=new String(p0,p1,p2);<br />else if (tag.equals("day")) day=new String(p0,p1,p2);<br />else if (tag.equals("month")) month=new String(p0,p1,p2);<br />else if (tag.equals("year")) year=new String(p0,p1,p2);<br />else if (tag.equals("description")) year=new String(p0,p1,p2);<br />}<br />private void printout(){<br />System.out.print("Content: ");<br />System.out.println(text);<br />System.out.print("URL: ");<br />System.out.println(url);<br />System.out.print("Author: ");<br />System.out.println(author);<br />System.out.print("Date: ");<br />System.out.println(day+"-"+month+"-"+year);<br />System.out.print("Description: ");<br />System.out.println(description);<br />System.out.println();<br />}<br />static public void main(String[] args) {<br />String filename = null;<br />boolean validation = false;<br />filename="links.xml";<br />SAXParserFactory spf = SAXParserFactory.newInstance();<br />SAXParser saxParser=null;<br />try {<br />saxParser = spf.newSAXParser();<br />} catch (Exception ex) {<br />System.err.println(ex);<br />System.exit(1);<br />}<br />try {<br />saxParser.parse(new File(filename),new SAXReader());<br />} catch (SAXException se) {<br />System.err.println(se.getMessage());<br />System.exit(1);<br />} catch (IOException ioe) {<br />System.err.println(ioe);<br />System.exit(1);<br />}<br />}<br />} <br /><br />在这儿虽然没有使用到栈的分析，但实际上栈的分析是一件很容易的事情，应为java.util.Stack继承了java.util.Vector类，而且Stack中的元素是按栈的结构由底至上排列的，因个，我们可以使用Vector类的size()方法来得到Stack的元素个数，还可以使用Vector的get(int)方法来得到具体的每一个元属。实际上，如果把Stack的元素从底向上逐一排列出来，我们就得到了从XML根节点到当前节点的一条唯一的路径，有了这条路径的信息，文档的结构就在清楚不过了。 <br /><br />小节 <br />好了，到这儿为止，我们已经掌握了对于XML编程的两大利器：DOM和SAX，也知道了该如何在一个Java程序中使用它们。DOM编程相对简单，但是速度比较慢，占用内存多，而SAX编程复杂一些，但是速度快，占用内存少。所以，我们应该根据不同的环境选择使用不同的方法。大部分的XML应用基本都可以用它们来解决。需要特别说明的是，DOM和SAX其实都是语言无关的，并非Java所独有，也就是说，只要有相应的语言实现，DOM和SAX可以应用在任何面向对象的语言中。 <br /><br />上面我们介绍了XML文档的读入，内容提取，以及文档添加和修改的一些方法。还有一类的问题就是XML文档的转换，虽然用DOM和SAX也可以解决，但是实现起来很复杂，而应用XSLT就会简单许多。这个问题，笔者将会在以后的文章中再和大家详细讨论<br /><img src ="http://www.blogjava.net/vso/aggbug/74811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 16:51 <a href="http://www.blogjava.net/vso/articles/74811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java与XML联合编程之DOM篇</title><link>http://www.blogjava.net/vso/articles/74810.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 08:50:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74810.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74810.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74810.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74810.html</trackback:ping><description><![CDATA[
		<strong>DOM初步</strong> <br /><br />DOM是Document Object Model的缩写，即文档对象模型。前面说过，XML将数据组织为一颗树，所以DOM就是对这颗树的一个对象描叙。通俗的说，就是通过解析XML文档，为XML文档在逻辑上建立一个树模型，树的节点是一个个对象。我们通过存取这些对象就能够存取XML文档的内容。 <br /><br />下面我们来看一个简单的例子，看看在DOM中，我们是如何来操作一个XML文档的。 <br /><br />这是一个XML文档，也是我们要操作的对象： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;messages&gt;<br />&lt;message&gt;Good-bye serialization, hello Java!&lt;/message&gt;<br />&lt;/messages&gt; <br /></pre><hr /></blockquote><br /><br />下面，我们需要把这个文档的内容解析到一个个的Java对象中去供程序使用，利用JAXP，我们只需几行代码就能做到这一点。首先，我们需要建立一个解析器工厂，以利用这个工厂来获得一个具体的解析器对象： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); <br /></pre><hr /></blockquote><br /><br />我们在这里使用DocumentBuilderFacotry的目的是为了创建与具体解析器无关的程序，当DocumentBuilderFactory类的静态方法newInstance()被调用时，它根据一个系统变量来决定具体使用哪一个解析器。又因为所有的解析器都服从于JAXP所定义的接口，所以无论具体使用哪一个解析器，代码都是一样的。所以当在不同的解析器之间进行切换时，只需要更改系统变量的值，而不用更改任何代码。这就是工厂所带来的好处。这个工厂模式的具体实现，可以参看下面的类图。 <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />DocumentBuilder db = dbf.newDocumentBuilder(); <br /></pre><hr /></blockquote><br /><br />当获得一个工厂对象后，使用它的静态方法newDocumentBuilder()方法可以获得一个DocumentBuilder对象，这个对象代表了具体的DOM解析器。但具体是哪一种解析器，微软的或者IBM的，对于程序而言并不重要。 <br /><br />然后，我们就可以利用这个解析器来对XML文档进行解析了： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />Document doc = db.parse("c:/xml/message.xml"); <br /></pre><hr /></blockquote><br /><br />DocumentBuilder的parse()方法接受一个XML文档名作为输入参数，返回一个Document对象，这个Document对象就代表了一个XML文档的树模型。以后所有的对XML文档的操作，都与解析器无关，直接在这个Document对象上进行操作就可以了。而具体对Document操作的方法，就是由DOM所定义的了。 <br /><a href="http://www0.ccidnet.com/tech/guide/2001/10/08/image/image002.gif" target="_blank"><img title="open in new window" alt="" src="http://www0.ccidnet.com/tech/guide/2001/10/08/image/image002.gif" border="0" /></a><br /><br />Jaxp支持W3C所推荐的DOM 2。如果你对DOM很熟悉，那么下面的内容就很简单了：只需要按照DOM的规范来进行方法调用就可以。当然，如果你对DOM不清楚，也不用着急，后面我们会有详细的介绍。在这儿，你所要知道并牢记的是：DOM是用来描叙XML文档中的数据的模型，引入DOM的全部原因就是为了用这个模型来操作XML文档的中的数据。DOM规范中定义有节点（即对象）、属性和方法，我们通过这些节点的存取来存取XML的数据。 <br /><br />从上面得到的Document对象开始，我们就可以开始我们的DOM之旅了。使用Document对象的getElementsByTagName()方法，我们可以得到一个NodeList对象，一个Node对象代表了一个XML文档中的一个标签元素，而NodeList对象，观其名而知其意，所代表的是一个Node对象的列表： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />NodeList nl = doc.getElementsByTagName("message"); <br /></pre><hr /></blockquote><br /><br />我们通过这样一条语句所得到的是XML文档中所有&lt;message&gt;标签对应的Node对象的一个列表。然后，我们可以使用NodeList对象的item()方法来得到列表中的每一个Node对象： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />Node my_node = nl.item(0); <br /></pre><hr /></blockquote><br /><br />当一个Node对象被建立之后，保存在XML文档中的数据就被提取出来并封装在这个Node中了。在这个例子中，要提取Message标签内的内容，我们通常会使用Node对象的getNodeValue()方法： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />String message = my_node.getFirstChild().getNodeValue(); <br /></pre><hr /></blockquote><br />请注意，这里还使用了一个getFirstChild()方法来获得message下面的第一个子Node对象。虽然在message标签下面除了文本外并没有其它子标签或者属性，但是我们坚持在这里使用getFirseChild()方法，这主要和W3C对DOM的定义有关。W3C把标签内的文本部分也定义成一个Node，所以先要得到代表文本的那个Node，我们才能够使用getNodeValue()来获取文本的内容。 <br /><br />现在，既然我们已经能够从XML文件中提取出数据了，我们就可以把这些数据用在合适的地方，来构筑应用程序。 <br /><br />下面的内容，我们将更多的关注DOM，为DOM作一个较为详细的解析，使我们使用起来更为得心应手。 <br /><br /><strong>DOM详解</strong> <br />1．基本的DOM对象 <br /><br />DOM的基本对象有5个：Document，Node，NodeList，Element和Attr。下面就这些对象的功能和实现的方法作一个大致的介绍。 <br /><a href="http://www0.ccidnet.com/tech/guide/2001/10/08/image/image004.gif" target="_blank"><img title="open in new window" alt="" src="http://www0.ccidnet.com/tech/guide/2001/10/08/image/image004.gif" border="0" /></a><br />Document对象代表了整个XML的文档，所有其它的Node，都以一定的顺序包含在Document对象之内，排列成一个树形的结构，程序员可以通过遍历这颗树来得到XML文档的所有的内容，这也是对XML文档操作的起点。我们总是先通过解析XML源文件而得到一个Document对象，然后再来执行后续的操作。此外，Document还包含了创建其它节点的方法，比如createAttribut()用来创建一个Attr对象。它所包含的主要的方法有： <br /><br />createAttribute(String)：用给定的属性名创建一个Attr对象，并可在其后使用setAttributeNode方法来放置在某一个Element对象上面。 <br /><br />createElement(String)：用给定的标签名创建一个Element对象，代表XML文档中的一个标签，然后就可以在这个Element对象上添加属性或进行其它的操作。 <br /><br />createTextNode(String)：用给定的字符串创建一个Text对象，Text对象代表了标签或者属性中所包含的纯文本字符串。如果在一个标签内没有其它的标签，那么标签内的文本所代表的Text对象是这个Element对象的唯一子对象。 <br /><br />getElementsByTagName(String)：返回一个NodeList对象，它包含了所有给定标签名字的标签。 <br /><br />getDocumentElement()：返回一个代表这个DOM树的根节点的Element对象，也就是代表XML文档根元素的那个对象。 <br /><br />Node对象是DOM结构中最为基本的对象，代表了文档树中的一个抽象的节点。在实际使用的时候，很少会真正的用到Node这个对象，而是用到诸如Element、Attr、Text等Node对象的子对象来操作文档。Node对象为这些对象提供了一个抽象的、公共的根。虽然在Node对象中定义了对其子节点进行存取的方法，但是有一些Node子对象，比如Text对象，它并不存在子节点，这一点是要注意的。Node对象所包含的主要的方法有： <br /><br />appendChild(org.w3c.dom.Node)：为这个节点添加一个子节点，并放在所有子节点的最后，如果这个子节点已经存在，则先把它删掉再添加进去。 <br /><br />getFirstChild()：如果节点存在子节点，则返回第一个子节点，对等的，还有getLastChild()方法返回最后一个子节点。 <br /><br />getNextSibling()：返回在DOM树中这个节点的下一个兄弟节点，对等的，还有getPreviousSibling()方法返回其前一个兄弟节点。 <br /><br />getNodeName()：根据节点的类型返回节点的名称。 <br /><br />getNodeType()：返回节点的类型。 <br /><br />getNodeValue()：返回节点的值。 <br /><br />hasChildNodes()：判断是不是存在有子节点。 <br /><br />hasAttributes()：判断这个节点是否存在有属性。 <br /><br />getOwnerDocument()：返回节点所处的Document对象。 <br /><br />insertBefore(org.w3c.dom.Node new，org.w3c.dom.Node ref)：在给定的一个子对象前再插入一个子对象。 <br /><br />removeChild(org.w3c.dom.Node)：删除给定的子节点对象。 <br /><br />replaceChild(org.w3c.dom.Node new，org.w3c.dom.Node old)：用一个新的Node对象代替给定的子节点对象。 <br /><br />NodeList对象，顾名思义，就是代表了一个包含了一个或者多个Node的列表。可以简单的把它看成一个Node的数组，我们可以通过方法来获得列表中的元素： <br /><br />GetLength()：返回列表的长度。 <br /><br />Item(int)：返回指定位置的Node对象。 <br /><br />Element对象代表的是XML文档中的标签元素，继承于Node，亦是Node的最主要的子对象。在标签中可以包含有属性，因而Element对象中有存取其属性的方法，而任何Node中定义的方法，也可以用在Element对象上面。 <br /><br />getElementsByTagName(String)：返回一个NodeList对象，它包含了在这个标签中其下的子孙节点中具有给定标签名字的标签。 <br /><br />getTagName()：返回一个代表这个标签名字的字符串。 <br /><br />getAttribute(String)：返回标签中给定属性名称的属性的值。在这儿需要主要的是，应为XML文档中允许有实体属性出现，而这个方法对这些实体属性并不适用。这时候需要用到getAttributeNodes()方法来得到一个Attr对象来进行进一步的操作。 <br /><br />getAttributeNode(String)：返回一个代表给定属性名称的Attr对象。 <br /><br />Attr对象代表了某个标签中的属性。Attr继承于Node，但是因为Attr实际上是包含在Element中的，它并不能被看作是Element的子对象，因而在DOM中Attr并不是DOM树的一部分，所以Node中的getparentNode()，getpreviousSibling()和getnextSibling()返回的都将是null。也就是说，Attr其实是被看作包含它的Element对象的一部分，它并不作为DOM树中单独的一个节点出现。这一点在使用的时候要同其它的Node子对象相区别。 <br /><br />需要说明的是，上面所说的DOM对象在DOM中都是用接口定义的，在定义的时候使用的是与具体语言无关的IDL语言来定义的。因而，DOM其实可以在任何面向对象的语言中实现，只要它实现了DOM所定义的接口和功能就可以了。同时，有些方法在DOM中并没有定义，是用IDL的属性来表达的，当被映射到具体的语言时，这些属性被映射为相应的方法。 <br /><br />2．DOM实例 <br /><br />有了上面的介绍，相信你对DOM理解的更多了吧。下面的例子将让你对DOM更加熟悉起来。 <br /><br />先说说这个例子到底要做的是什么吧，我们希望在一个名为link.xml文件中保存了一些URL地址，通过一个简单的程序，我们可以通过DOM把这些URL读出并显示出来，也可以反过来向这个XML文件中写入加入的URL地址。很简单，却很实用，也足够来例示DOM的绝大部分用法了。 <br /><br />XML文件本身不复杂，就不给出它的DTD了。link.xml: <br /><br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;?xml version="1.0" standalone="yes"?&gt;<br />&lt;links&gt;<br />&lt;link&gt;<br />&lt;text&gt;JSP Insider&lt;/text&gt;<br />&lt;url newWindow="no"&gt;http://www.jspinsider.com&lt;/url&gt;<br />&lt;author&gt;JSP Insider&lt;/author&gt;<br />&lt;date&gt;<br />&lt;day&gt;2&lt;/day&gt;<br />&lt;month&gt;1&lt;/month&gt;<br />&lt;year&gt;2001&lt;/year&gt;<br />&lt;/date&gt;<br />&lt;description&gt;A JSP information site.&lt;/description&gt;<br />&lt;/link&gt;<br />&lt;link&gt;<br />&lt;text&gt;The makers of Java&lt;/text&gt;<br />&lt;url newWindow="no"&gt;http://java.sun.com&lt;/url&gt;<br />&lt;author&gt;Sun Microsystems&lt;/author&gt;<br />&lt;date&gt;<br />&lt;day&gt;3&lt;/day&gt;<br />&lt;month&gt;1&lt;/month&gt;<br />&lt;year&gt;2001&lt;/year&gt;<br />&lt;/date&gt;<br />&lt;description&gt;Sun Microsystem's website.&lt;/description&gt;<br />&lt;/link&gt;<br />&lt;link&gt;<br />&lt;text&gt;The standard JSP container&lt;/text&gt;<br />&lt;url newWindow="no"&gt;http://jakarta.apache.org&lt;/url&gt;<br />&lt;author&gt;Apache Group&lt;/author&gt;<br />&lt;date&gt;<br />&lt;day&gt;4&lt;/day&gt;<br />&lt;month&gt;1&lt;/month&gt;<br />&lt;year&gt;2001&lt;/year&gt;<br />&lt;/date&gt;<br />&lt;description&gt;Some great software.&lt;/description&gt;<br />&lt;/link&gt;<br />&lt;/links&gt; <br /><br /></pre><hr /></blockquote><br />第一个程序我们称为xmldisplay.java，具体的程序清单可以在附件中找到。主要的功能就是读取这个XML文件中各个节点的内容，然后在格式化输出在System.out上，我们来看看这个程序： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />import javax.xml.parsers.*;<br />import org.w3c.dom.*; <br /></pre><hr /></blockquote><br />这是引入必要的类，因为在这里使用的是Sun所提供的XML解析器，因而需要引入java.xml.parsers包，其中包含了有DOM解析器和SAX解析器的具体实现。org.w3c.dom包中定义了w3c所制定的DOM接口。 <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();<br />DocumentBuilder builder=factory.newDocumentBuilder();<br />Document doc=builder.parse("links.xml");<br />doc.normalize(); <br /></pre><hr /></blockquote><br />除了上面讲到的，还有一个小技巧，对Document对象调用normalize()，可以去掉XML文档中作为格式化内容的空白而映射在DOM树中的不必要的Text Node对象。否则你得到的DOM树可能并不如你所想象的那样。特别是在输出的时候，这个normalize()更为有用。 <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />NodeList links =doc.getElementsByTagName("link"); <br /></pre><hr /></blockquote><br />刚才说过，XML文档中的空白符也会被作为对象映射在DOM树中。因而，直接调用Node方法的getChildNodes方法有时候会有些问题，有时不能够返回所期望的NodeList对象。解决的办法是使用Element的getElementByTagName(String)，返回的NodeLise就是所期待的对象了。然后，可以用item()方法提取想要的元素。 <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />for (int i=0;i&lt;links.getLength();i++){<br />Element link=(Element) links.item(i);<br />System.out.print("Content: ");<br />System.out.println(link.getElementsByTagName("text").item(0).getFirstChild().getNodeValue());<br />System.out.print("URL: ");<br />System.out.println(link.getElementsByTagName("url").item(0).getFirstChild().getNodeValue());<br />System.out.print("Author: ");<br />System.out.println(link.getElementsByTagName("author").item(0).getFirstChild().getNodeValue());<br />System.out.print("Date: ");<br />Element linkdate=(Element) link.getElementsByTagName("date").item(0);<br />String day=linkdate.getElementsByTagName("day").item(0).getFirstChild().getNodeValue();<br />String month=linkdate.getElementsByTagName("month").item(0).getFirstChild().getNodeValue();<br />String year=linkdate.getElementsByTagName("year").item(0).getFirstChild().getNodeValue();<br />System.out.println(day+"-"+month+"-"+year);<br />System.out.print("Description: ");<br />System.out.println(link.getElementsByTagName("description").item(0).getFirstChild().getNodeValue());<br />System.out.println();<br />} <br /></pre><hr /></blockquote><br />上面的代码片断就完成了对XML文档内容的格式化输出。只要注意到一些细节的问题，比如getFirstChile()方法和getElementsByTagName()方法的使用，这些还是比较容易的。 <br /><br />下面的内容，就是在修改了DOM树后重新写入到XML文档中去的问题了。这个程序名为xmlwrite.java。在JAXP1.0版本中，并没有直接的类和方法能够处理XML文档的写入问题，需要借助其它包中的一些辅助类。而在JAXP1.1版本中，引入了对XSLT的支持，所谓XSLT，就是对XML文档进行变换（Translation）后，得到一个新的文档结构。利用这个新加入的功能，我们就能够很方便的把新生成或者修改后的DOM树从新写回到XML文件中去了，下面我们来看看代码的实现，这段代码的主要功能是向links.xml文件中加入一个新的link节点： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />import javax.xml.parsers.*;<br />import javax.xml.transform.*;<br />import javax.xml.transform.dom.DOMSource;<br />import javax.xml.transform.stream.StreamResult;<br />import org.w3c.dom.*; <br /></pre><hr /></blockquote><br />新引入的java.xml.transform包中的几个类，就是用来处理XSLT变换的。 <br /><br />我们希望在上面的XML文件中加入一个新的link节点，因而首先还是要读入links.xml文件，构建一个DOM树，然后再对这个DOM树进行修改（添加节点），最后把修改后的DOM写回到links.xml文件中： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();<br />DocumentBuilder builder=factory.newDocumentBuilder();<br />Document doc=builder.parse("links.xml");<br />doc.normalize();<br />//---取得变量----<br />String text="Hanzhong's Homepage";<br />String url="www.hzliu.com";<br />String author="Hzliu Liu";<br />String discription="A site from Hanzhong Liu, give u lots of suprise!!!"; <br /></pre><hr /></blockquote><br />为了看清重点，简化程序，我们把要加入的内容硬编码到记忆String对象中，而实际操作中，往往利用一个界面来提取用户输入，或者通过JDBC从数据库中提取想要的内容。 <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />Text textseg;<br />Element link=doc.createElement("link"); <br /></pre><hr /></blockquote><br />首先应该明了的是，无论什么类型的Node，Text型的也好，Attr型的也好，Element型的也好，它们的创建都是通过Document对象中的createXXX()方法来创建的（XXX代表具体要创建的类型），因此，我们要向XML文档中添加一个link项目，首先要创建一个link对象： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />Element linktext=doc.createElement("text");<br />textseg=doc.createTextNode(text);<br />linktext.appendChild(textseg);<br />link.appendChild(linktext);<br />Element linkurl=doc.createElement("url");<br />textseg=doc.createTextNode(url);<br />linkurl.appendChild(textseg);<br />link.appendChild(linkurl);<br />Element linkauthor=doc.createElement("author");<br />textseg=doc.createTextNode(author);<br />linkauthor.appendChild(textseg);<br />link.appendChild(linkauthor);<br />java.util.Calendar rightNow = java.util.Calendar.getInstance();<br />String day=Integer.toString(rightNow.get(java.util.Calendar.DAY_OF_MONTH));<br />String month=Integer.toString(rightNow.get(java.util.Calendar.MONTH));<br />String year=Integer.toString(rightNow.get(java.util.Calendar.YEAR));<br />Element linkdate=doc.createElement("date");<br />Element linkdateday=doc.createElement("day");<br />textseg=doc.createTextNode(day);<br />linkdateday.appendChild(textseg);<br />Element linkdatemonth=doc.createElement("month");<br />textseg=doc.createTextNode(month);<br />linkdatemonth.appendChild(textseg);<br />Element linkdateyear=doc.createElement("year");<br />textseg=doc.createTextNode(year);<br />linkdateyear.appendChild(textseg);<br />linkdate.appendChild(linkdateday);<br />linkdate.appendChild(linkdatemonth);<br />linkdate.appendChild(linkdateyear);<br />link.appendChild(linkdate);<br />Element linkdiscription=doc.createElement("description");<br />textseg=doc.createTextNode(discription);<br />linkdiscription.appendChild(textseg);<br />link.appendChild(linkdiscription); <br /></pre><hr /></blockquote><br />创建节点的过程可能有些千篇一律，但需要注意的地方是，对Element中所包含的text（在DOM中，这些text也是代表了一个Node的，因此也必须为它们创建相应的node），不能直接用Element对象的setNodeValue()方法来设置这些text的内容，而需要用创建的Text对象的setNodeValue()方法来设置文本，这样才能够把创建的Element和其文本内容添加到DOM树中。看看前面的代码，你会更好的理解这一点： <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />doc.getDocumentElement().appendChild(link); <br /></pre><hr /></blockquote><br />最后，不要忘记把创建好的节点添加到DOM树中。Document类的getDocumentElement()方法，返回代表文档根节点的Element对象。在XML文档中，根节点一定是唯一的。 <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />TransformerFactory tFactory =TransformerFactory.newInstance();<br />Transformer transformer = tFactory.newTransformer();<br />DOMSource source = new DOMSource(doc);<br />StreamResult result = new StreamResult(new java.io.File("links.xml"));<br />transformer.transform(source, result); <br /></pre><hr /></blockquote><br />然后就是用XSLT把DOM树输出了。这里的TransformerFactory也同样应用了工厂模式，使得具体的代码同具体的变换器无关。实现的方法和DocumentBuilderFactory相同，这儿就不赘述了。Transformer类的transfrom方法接受两个参数、一个数据源Source和一个输出目标Result。这里分别使用的是DOMSource和StreamResult，这样就能够把DOM的内容输出到一个输出流中，当这个输出流是一个文件的时候，DOM的内容就被写入到文件中去了。<br /><img src ="http://www.blogjava.net/vso/aggbug/74810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 16:50 <a href="http://www.blogjava.net/vso/articles/74810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用JDOM处理XML文档</title><link>http://www.blogjava.net/vso/articles/74809.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 08:48:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74809.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74809.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74809.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74809.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74809.html</trackback:ping><description><![CDATA[关键词：Java、JDOM、XML、JAXB<br />欢迎与我讨论（boyofjava@sina.com）<br /><br />（一）JDOM的介绍以及与JAXB的比较<br /><br />Java + XML = JDOM ！<br />这就是JDOM设计者的目标。如果你曾经使用过烦人的SAX或是DOM来处理XML，你就会知道为什么要有JDOM或者是JAXB。在今年（2002）的JavaOne会议上JDOM的主要创始人Jason Hunter有一篇精彩的演讲介绍了JDOM技术，题目就是JDOM Makes XML Easy。<br />在那篇文档里，JDOM被拿来与DOM比较，而我更愿意拿它同JAXB比较。因为JAXB和JDOM都是为了在Java中提供比DOM和SAX更为方便的XML处理接口而开发的，并且通过完全不同的途径来解决这个问题。JDOM的处理方式是与DOM类似的树操作。而JAXB通过DTD和绑定模式来生成访问XML文档的Java代码，将XML映射成了Java对象来操作。你可以根据项目的需要和个人喜好来决定采用哪一个。<br />JDOM与JAXB的比较，从本身的特点来看：<br />1)    JDOM比JAXB更容易上手。使用JAXB首先要会编写DTD，然后还要会编写绑定模式。JDOM没有这样的要求，如果你会Java和XML，甚至可以说光是看JDOM的javadoc文档就能够使用JDOM。<br />2)    JAXB编写好DTD和绑定模式以后，XML文档被映射成了Java对象，其数据就是Java对象的属性，连数据类型都做好了转换，因此，访问XML文档比JDOM要简便，可以说是一劳永逸。<br />3)    JAXB由某个DTD和绑定模式生成的代码只能访问该DTD所约束的文档。如果想要访问其他XML文档，需要再编写DTD和绑定模式。JDOM可以处理任何XML文档，包括受约束的和不受约束的。<br /><br />目前JDOM和JAXB都没有正式版本。JDOM的最新版本是beta8，JAXB是1.0 early access，其规范版本是0.21。相对而言，JDOM更成熟一些。例如JAXB不支持名字空间、不能向XML文档写入处理指令，有时我们需要保留的换行符和首尾空格在JAXB中自动过滤掉了，就连放在&lt;![CDATA[ 和 ]]&gt;里面也不能幸免。JDOM就没有这些限制。如果说以上的3点比较是JDOM和JAXB本身的特点所决定的，几乎不可能改变，那么这里表明，JAXB还需要更多的工作。<br /><br />（二）获得并安装JDOM<br />在http://jdom.org可以下载JDOM的最新版本。以JDOM beta8的2进制版本为例。下载后解压缩，JDOM的jar文件就是build目录下的文件jdom.jar，将之加入类路径。另外JDOM还需要lib目录下那些jar文件如xerces.jar的支持。如果在使用中出现以下错误：<br />java.lang.NoSuchMethodError<br />或 <br />java.lang.NoClassDefFoundError: org/xml/sax/SAXNotRecognizedException<br />你需要保证xerces.jar文件在CLASSPATH中位于其他XML类，如JAXP或Crimson之前，这些类文件，包括以前老版本的xerces，可能不支持SAX2.0或DOM Level 2。于是导致了上面的错误。<br /><br />（三）一个简单的例子<br />JDOM的处理方式有些类似于DOM，但它主要是用SAX实现的，你不必担心处理速度和内存的问题。另外，JDOM中几乎没有接口，的类全部是实实在在的类，没有类工厂类的。其最重要的一个包org.jdom中主要有以下类：<br />? Attribute<br />? CDATA<br />? Comment<br />? DocType<br />? Document<br />? Element<br />? EntityRef<br />? Namespace<br />? ProcessingInstruction<br />?    Text<br />数据输入要用到XML文档要通过org.jdom.input包，反过来需要org.jdom.output。如前面所说，关是看API文档就能够使用。<br />我们的例子读入XML文件exampleA.xml，加入一条处理指令，修改第一本书的价格和作者，并添加一条属性，然后写入文件exampleB.xml：<br />//exampleA.xml<br />&lt;?xml version="1.0" encoding="GBK"?&gt;<br />&lt;bookList&gt;<br />    &lt;book&gt;<br />        &lt;name&gt;Java编程入门&lt;/name&gt;<br />        &lt;author&gt;张三&lt;/author&gt;<br />        &lt;publishDate&gt;2002-6-6&lt;/publishDate&gt;<br />        &lt;price&gt;35.0&lt;/price&gt;<br />    &lt;/book&gt;<br />    &lt;book&gt;<br />        &lt;name&gt;XML在Java中的应用&lt;/name&gt;<br />        &lt;author&gt;李四&lt;/author&gt;<br />        &lt;publishDate&gt;2002-9-16&lt;/publishDate&gt;<br />        &lt;price&gt;92.0&lt;/price&gt;<br />    &lt;/book&gt;<br />&lt;/bookList&gt;<br /><br />//testJDOM.java<br />import org.jdom.*;<br />import org.jdom.output.*;<br />import org.jdom.input.*;<br />import java.io.*;<br />public class TestJDOM{<br />    public static void main(String args[])throws Exception{<br />        <br />        SAXBuilder sb = new SAXBuilder();<br /><br />        //从文件构造一个Document，因为XML文件中已经指定了编码，所以这里不必了<br />        Document doc = sb.build(new FileInputStream("exampleA.xml"));<br />        <br />        //加入一条处理指令\<br />        ProcessingInstruction pi = new ProcessingInstruction<br />            ("xml-stylesheet","href=\"bookList.html.xsl\" type=\"text/xsl\"");<br />        doc.addContent(pi);<br /><br /><br />        Element root = doc.getRootElement(); //得到根元素<br />        java.util.List books = root.getChildren(); //得到根元素所有子元素的集合<br />        Element book = (Element)books.get(0); //得到第一个book元素<br />        //为第一本书添加一条属性<br />        Attribute a = new Attribute("hot","true");  <br />        book.setAttribute(a);<br />        Element author = book.getChild("author"); //得到指定的字元素<br />        author.setText("王五\\"); //将作者改为王五<br />        //或 Text t = new Text("王五\\");book.addContent(t);<br />        Element price = book.getChild("price"); //得到指定的字元素<br />        //修改价格，比较郁闷的是我们必须自己转换数据类型，而这正是JAXB的优势<br />        author.setText(Float.toString(50.0f)); <br />        <br /><br /><br />        String indent = "    ";<br />        boolean newLines = true;<br />        XMLOutputter outp = new XMLOutputter(indent,newLines,"GBK");<br />        outp.output(doc, new FileOutputStream("exampleB.xml"));<br /><br />    }<br />};<br /><br />执行结果exampleB.xml：<br />&lt;?xml version="1.0" encoding="GBK"?&gt;<br />&lt;bookList&gt;<br />    &lt;book hot=”true”&gt;<br />        &lt;name&gt;Java编程入门&lt;/name&gt;<br />        &lt;author&gt;50.0&lt;/author&gt;<br />        &lt;publishDate&gt;2002-6-6&lt;/publishDate&gt;<br />        &lt;price&gt;35.0&lt;/price&gt;<br />    &lt;/book&gt;<br />    &lt;book&gt;<br />        &lt;name&gt;XML在Java中的应用&lt;/name&gt;<br />        &lt;author&gt;李四&lt;/author&gt;<br />        &lt;publishDate&gt;2002-9-16&lt;/publishDate&gt;<br />        &lt;price&gt;92.0&lt;/price&gt;<br />    &lt;/book&gt;<br />&lt;/bookList&gt;<br />&lt;?xml-stylesheet href="bookList.html.xsl" type="text/xsl"?&gt;<br /><br />在默认情况下，JDOM的Element类的getText()这类的方法不会过滤空白字符，如果你需要过滤，用setTextTrim() 。<br /><br /><br />（四）参考文档<br />1)    JDOM Makes XML Easy (http://www.servlets.com/speaking/jdom-javaone.pdf)<br />2)    The Java &amp;#8482; Architecture for XML Binding User’s Guide (http://java.sun.com/xml/jaxb/jaxb-docs.pdf)<br />3)    Web Services Made Easier. The Java TM APIs and Architectures for XML, A Technical White Paper (http://java.sun.com/xml/webservices.pdf )<br /><img src ="http://www.blogjava.net/vso/aggbug/74809.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 16:48 <a href="http://www.blogjava.net/vso/articles/74809.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java编程中更新XML文档的常用方法</title><link>http://www.blogjava.net/vso/articles/74808.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 08:47:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74808.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74808.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74808.html</trackback:ping><description><![CDATA[本文简要的讨论了Java语言编程中更新XML文档的四种常用方法,并且分析这四种方法的优劣。其次,本文还对如何控制Java程序输出的XML文档的格式做了展开论述。 <br /><br /><br /><br />JAXP是Java API for XML Processing的英文字头缩写,中文含义是:用于XML文档处理的使用Java语言编写的编程接口。JAXP支持DOM、SAX、XSLT等标准。为了增强JAXP使用上的灵活性,开发者特别为JAXP设计了一个Pluggability Layer,在Pluggability Layer的支持之下,JAXP既可以和具体实现DOM API、SAX API 的各种XML解析器(XML Parser,例如Apache Xerces)联合工作,又可以和具体执行XSLT标准的XSLT处理器(XSLT Processor,例如Apache Xalan)联合工作。应用Pluggability Layer的好处在于:我们只需要熟悉JAXP各个编程接口的定义即可,而不需要对所采用的具体的XML解析器、XSLT处理器有很深入的了解。比如在某个Java程序中,通过JAXP调用XML解析器Apache Crimson对XML文档进行处理,如果我们希望使用别的XML解析器(比如Apache Xerces),以便提高该程序的性能,那么原程序代码可能不需要任何改变,直接就可以使用(你所需要做的事情只是将包含Apache Xerces代码的jar文件加入到环境变量CLASSPATH中,而将包含Apache Crimson代码的jar文件在环境变量CLASSPATH中删除)。 <br /><br /><br /><br />目前JAXP已经应用的十分普遍了,可以说是Java语言中处理XML文档的标准API。有些初学者在学习使用JAXP的过程中,经常会提出这样的问题:我编写的程序对DOM Tree做了更新,但是当程序退出以后,原始的XML文档并没有改变,还是老样子,如何实现对原始XML文档和DOM Tree的同步更新呢?咋一看来,在JAXP中似乎没有提供相应的接口/方法/类,这是很多初学者都感到困惑的问题。本文的主旨就在于解决这个问题,简单的介绍几种常用的同步更新原始XML文档和DOM Tree的方法。为了缩小讨论的范围,本文所涉及的XML解析器仅包括Apache Crimson和Apache Xerces,而XSLT处理器仅仅使用Apache Xalan。 <br /><br /><br /><br />方法一:直接读写XML文档 <br /><br /><br /><br />这也许是最笨最原始的办法了。当程序获取DOM Tree之后,应用DOM模型的Node接口的各个方法对DOM Tree进行更新,下一步应该对原始的XML文档进行更新了。我们可以运用递归的办法或者是应用TreeWalker类,遍历整个DOM Tree,与此同时,将DOM Tree的每一个节点/元素依次写入到预先打开的原始XML文档中,当DOM Tree被遍历完全之后,DOM Tree和原始的XML文档就实现了同步更新。实际中,这个方法极少使用,不过如果你要编程实现自己的XML解析器,这种方法还是有可能用得上的。 <br /><br /><br /><br />方法二:使用XmlDocument类 <br /><br /><br /><br />使用XmlDocument类?JAXP中分明没有这个类呀!是不是作者搞错了?没有错!就是使用XmlDocument类,确切的说,是使用XmlDocument类的write()方法。 <br /><br /><br /><br />在上文已经提到过,JAXP可以和各种各样的XML解析器联合使用,这次我们选用的XML解析器是Apache Crimson。XmlDocument(org.apache.crimson.tree.XmlDocument)是Apache Crimson的一个类,并不包含于标准的JAXP中,难怪在JAXP的文档中找不到XmlDocument类的芳踪呢。现在问题出来了,如何应用XmlDocument类来实现更新XML文档的功能?在XmlDocument类中提供了下面三个write()方法(根据Crimson最新的版本------Apache Crimson 1.1.3): <br /><br /><br /><br /><br /><br /><br /><br />public void write (OutputStream out) throws IOException <br /><br />public void write (Writer out) throws IOException <br /><br />public void write (Writer out, String encoding) throws IOException <br /><br /><br /><br /><br /><br /><br /><br />上述三个write()方法的主要作用就是输出DOM Tree中的内容到特定的输出介质中,比如文件输出流、应用程序控制台等等。那么又如何使用上述三个write()方法呢?请看下面的Java程序代码片断: <br /><br /><br /><br /><br /><br />String name="fancy"; <br /><br />DocumentBuilder parser; <br /><br />DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); <br /><br />try <br /><br />{ <br /><br />parser = factory.newDocumentBuilder(); <br /><br />Document doc = parser.parse("user.xml"); <br /><br />Element newlink=doc.createElement(name); <br /><br />doc.getDocumentElement().appendChild(newlink); <br /><br />((XmlDocument)doc).write(new FileOutputStream(new File("xuser1.xml"))); <br /><br />} <br /><br />catch (Exception e) <br /><br />{ <br /><br />//to log it <br /><br />} <br /><br /><br /><br /><br /><br /><br /><br />在上面的代码中,首先创建了一个Document对象doc,获取完整的DOM Tree,然后应用Node接口的appendChild()方法,在DOM Tree的最后追加了一个新节点(fancy),最后调用XmlDocument类的write(OutputStream out)方法,把DOM Tree中的内容输出到xuser.xml中(其实也可以输出到user.xml,更新原始的XML文档,在这里为了便于做对比,故而输出到xuser.xml文件中)。需要注意的是不能直接对Document对象doc直接调用write()方法,因为JAXP的Document接口并没有定义任何write()方法,所以必须将doc由Document对象强制转换为XmlDocument对象,然后才能调用write()方法,在上面的代码中使用的是write(OutputStream out)方法,这个方法使用缺省的UTF-8编码输出DOM Tree中的内容到特定的输出介质中,如果DOM Tree中包含中文字符,那么输出的结果有可能是乱码,亦即存在所谓的"汉字问题\\",解决的办法是使用write (Writer out, String encoding)方法,显式指定输出时的编码,例如将第二个参数设为"GB2312",这时即不存在"汉字问题\\",输出结果能够正常显示中文字符。 <br /><br /><br /><br />完整的例子请参考下列文件: AddRecord.java(见附件)、user.xml(见附件)。该例子的运行环境为:Windows XP Professional、JDK 1.3.1。为了能够正常编译运行AddRecord.java这个程序,你需要到网址http://xml.apache.org/dist/crimson/去下载Apache Crimson,并将所获取的crimson.jar文件加入到环境变量CLASSPATH中。 <br /><br /><br /><br />注意: <br /><br /><br /><br />Apache Crimson的前身是Sun Project X Parser,后来不知何故,由X Parser演变为Apache Crimson,至今Apache Crimson的很多代码都是从X Parser中直接移植过来的。比如上文用到的XmlDocument类,它在X Parser中是com.sun.xml.XmlDocument,到了Apache Crimson中摇身一变,就变成了org.apache.crimson.tree.XmlDocument类,其实它们的绝大部分代码是一样的,可能就package语句和import语句以及文件开头的一段lience有所不同而已。早期的JAXP是和X Parser捆绑在一起的,因此一些老的程序使用了com.sun.xml包,如果你现在重新编译它们,有可能不能通过,肯定就是因为这个原因。后来的JAXP和Apache Crimson捆绑在一起,比如JAXP 1.1,如果你使用JAXP 1.1,那么不需要额外下载Apache Crimson,也能够正常编译运行上面的例子(AddRecord.java)。最新的JAXP 1.2 EA(Early Access)改弦更张,采用性能更好的Apache Xalan和Apache Xerces分别作为XSLT处理器和XML解析器,不能直接支持Apache Crimson了,所以如果你的开发环境采用了JAXP 1.2 EA或者是Java XML Pack(内含JAXP 1.2 EA),那么将无法直接编译运行上面的例子(AddRecord.java),你需要额外下载并安装Apache Crimson。 <br /><br /><br /><br />方法三:使用TransformerFactory和Transformer类 <br /><br /><br /><br />在JAXP中所提供的标准的更新原始XML文档的方法就是调用XSLT引擎,亦即使用TransformerFactory和Transformer类。请看下面的Java代码片断: <br /><br /><br /><br /><br /><br />//首先创建一个DOMSource对象,该构造函数的参数可以是一个Document对象 <br /><br />//doc代表更改后的DOM Tree。 <br /><br />DOMSource doms = new DOMSource (doc); <br /><br /><br /><br />//创建一个File对象,代表DOM Tree所包含的数据的输出介质,这是一个XML文件。 <br /><br />File f = new File ("XMLOutput.xml"); <br /><br /><br /><br />//创建一个StreamResult对象,该构造函数的参数可以取为File对象。 <br /><br />StreamResult sr = new StreamResult (f); <br /><br /><br /><br />//下面调用JAXP中的XSLT引擎来实现输出DOM Tree中的数据到XML文件中的功能。 <br /><br />//XSLT引擎的输入为DOMSource对象,输出为StreamResut对象。 <br /><br />try <br /><br />{ <br /><br />//首先创建一个TransformerFactory对象,再由此创建Transformer对象。Transformer <br /><br />//类相当于一个XSLT引擎。通常我们使用它来处理XSL文件,但是在这里我们使 <br /><br />//用它来输出XML文档。 <br /><br />TransformerFactory tf=TransformerFactory.newInstance(); <br /><br />Transformer t=tf.newTransformer (); <br /><br /><br /><br />//关键的一步, 调用Transformer对象 (XSLT引擎)的transform()方法,该方法的第一 <br /><br />//个参数是DOMSource对象,第二个参数是StreamResult对象。 <br /><br />t.transform(doms,sr); <br /><br />} <br /><br />catch (TransformerConfigurationException tce) <br /><br />{ <br /><br />System.out.println("Transformer Configuration Exception<br />-----"); <br /><br />tce.printStackTrace(); <br /><br />} <br /><br />catch (TransformerException te) <br /><br />{ <br /><br />System.out.println ("Transformer Exception<br />---------"); <br /><br />te.printStackTrace (); <br /><br />} <br /><br /><br /><br /><br /><br />在实际的应用中,我们可以应用传统的DOM API从XML文档中获取DOM Tree,然后根据实际的需求对DOM Tree执行各种操作,得到最终的Document对象,接下来可以由此Document对象创建DOMSource对象,剩下的事情就是照搬上面的代码了,程序运行完毕后, XMLOutput.xml就是你所需要的结果(当然了,你可以随意更改StreamResult类构造函数的参数,指定不同的输出介质,而不必是千篇一律的XML文档)。 <br /><br /><br /><br />这个方法最大的好处在于可以随心所欲的控制DOM Tree中的内容输出到输出介质中的格式,但是光靠TransformerFactory类和Transformer类并不能实现这个功能,还需要依赖OutputKeys类的帮助。 完整的例子请参考下列文件: AddRecord2.java(见附件)、user.xml(见附件)。该例子的运行环境为:Windows XP Professional、JDK 1.3.1。为了能够正常编译运行AddRecord2.java这个程序,你需要到网址http://java.sun.com去下载安装JAXP 1.1或者Java XML Pack(Java XML Pack已经内含JAXP了)。 <br /><br /><br /><br />OutputKeys类 <br /><br /><br /><br />javax.xml.transform.OutputKeys类和java.util.Properties类配合使用,可以控制JAXP的XSLT引擎(Transformer类)输出XML文档的格式。请看下面的代码片断: <br /><br /><br /><br /><br /><br />//首先创建一个TransformerFactory对象,再由此创建Transformer对象。 <br /><br />TransformerFactory tf=TransformerFactory.newInstance(); <br /><br />Transformer t=tf.newTransformer (); <br /><br /><br /><br />//获取Transformser对象的输出属性,亦即XSLT引擎的缺省输出属性,这是一个 <br /><br />//java.util.Properties对象。 <br /><br />Properties properties = t.getOutputProperties(); <br /><br /><br /><br />//设置新的输出属性:输出字符编码为GB2312,这样可以支持中文字符,XSLT引擎所输出 <br /><br />//的XML文档如果包含了中文字符,可以正常显示,不会出现所谓的"汉字问题\\"。 <br /><br />//请留意OutputKeys类的字符串常数OutputKeys.ENCODING。 <br /><br />properties.setProperty(OutputKeys.ENCODING,"GB2312"); <br /><br /><br /><br />/更新XSLT引擎的输出属性。 <br /><br />t.setOutputProperties(properties); <br /><br /><br /><br />//调用XSLT引擎,按照输出属性中的设置,输出DOM Tree中的内容到输出介质中。 <br /><br />t.transform(DOMSource_Object,StreamResult_Object); <br /><br /><br /><br /><br /><br /><br /><br /><br /><br />从上面的程序代码,我们不难看出,通过设置XSLT引擎(Transformer类)的输出属性,可以控制DOM Tree中的内容的输出格式,这对于我们定制输出内容是很有帮助的。那么JAXP的XSLT引擎(Transformer类)有那些输出属性可以设置呢? javax.xml.transform.OutputKeys类定义了很多字符串常数,它们都是可以自由设置的输出属性,常用的输出属性如下所示: <br /><br /><br /><br />public static final java.lang.String METHOD <br /><br /><br /><br /><br /><br />可以设为"xml"、"html"、"text"等值。 <br /><br /><br /><br />public static final java.lang.String VERSION <br /><br /><br /><br /><br /><br />所遵循规范的版本号,如果METHOD设为"xml",那么它的值应该设为"1.0",如果METHOD设为"html",那么它的值应该设为"4.0",如果METHOD设为"text",那么这个输出属性会被忽略。 <br /><br /><br /><br />public static final java.lang.String ENCODING <br /><br /><br /><br /><br /><br />设置输出时所采用的编码方式,比如\\"GB2312"、"UTF-8"等等,如果将其设置为"GB2312",可以解决所谓的"汉字问题\\"。 <br /><br /><br /><br />public static final java.lang.String OMIT_XML_DECLARATION <br /><br /><br /><br />设置输出到XML文档中时是否忽略XML声明,亦即类似于: <br /><br /><br /><br />&lt;?xml version="1.0" standalone="yes" encoding="utf-8" ?&gt; <br /><br /><br /><br /><br /><br />这样的代码。它可选的值有"yes"、"no"。 <br /><br /><br /><br />public static final java.lang.String INDENT <br /><br /><br /><br /><br /><br />IDENT设定XSLT引擎在输出XML文档时,是否自动添加额外的空格,它可选的值为"yes"、"no"。 <br /><br /><br /><br />public static final java.lang.String MEDIA_TYPE <br /><br /><br /><br />MEDIA_TYPE设定输出文档的MIME类型。 <br /><br /><br /><br />如果设定XSLT引擎的输出属性呢?下面我们来总结一下: <br /><br /><br /><br />首先是获取XSLT引擎(Transformer类)的缺省输出属性的集合,这需要使用Transformer类的getOutputProperties()方法,返回值是一个java.util.Properties对象。 <br /><br /><br /><br />Properties properties = transformer.getOutputProperties(); <br /><br /><br /><br /><br /><br />然后是设定新的输出属性,比如: <br /><br /><br /><br />properties.setProperty(OutputKeys.ENCODING,"GB2312"); <br /><br />properties.setProperty(OutputKeys.METHOD,"html"); <br /><br />properties.setProperty(OutputKeys.VERSION,"4.0"); <br /><br />……………………………………………………… <br /><br /><br /><br /><br /><br />最后是更新XSLT引擎(Transformer类)的缺省输出属性的集合,这需要使用Transformer类的setOutputProperties()方法,参数是一个java.util.Properties对象。 <br /><br /><br /><br />我们编写了一个新的程序,其中应用了OutputKeys类,用以控制XSLT引擎的输出属性,该程序的架构和前一个程序(AddRecord3.java)大致相同,不过输出结果略有不同。完整的代码请参考下列文件: AddRecord3.java(见附件)、user.xml(见附件)。该例子的运行环境为:Windows XP Professional、JDK 1.3.1。为了能够正常编译运行AddRecord3.java这个程序,你需要到网址http://java.sun.com去下载安装JAXP 1.1或者Java XML Pack(Java XML Pack内含JAXP了)。 <br /><br /><br /><br />方法四:使用Xalan XML Serializer <br /><br /><br /><br />方法四其实是方法三的一个变种,它需要Apache Xalan和Apache Xerces的支持才能够运行。例子代码如下所示: <br /><br /><br /><br /><br /><br />//首先创建一个DOMSource对象,该构造函数的参数可以是一个Document对象 <br /><br />//doc代表更改后的DOM Tree。 <br /><br />DOMSource domSource = new DOMSource (doc); <br /><br /><br /><br />//创建一个DOMResult对象,临时保存XSLT引擎的输出结果。 <br /><br />DOMResult domResult = new DOMResult(); <br /><br /><br /><br />//下面调用JAXP中的XSLT引擎来实现输出DOM Tree中的数据到XML文件中的功能。 <br /><br />//XSLT引擎的输入为DOMSource对象,输出为DOMResut对象。 <br /><br />try <br /><br />{ <br /><br />//首先创建一个TransformerFactory对象,再由此创建Transformer对象。Transformer <br /><br />//类相当于一个XSLT引擎。通常我们使用它来处理XSL文件,但是在这里我们使 <br /><br />//用它来输出XML文档。 <br /><br />TransformerFactory tf=TransformerFactory.newInstance(); <br /><br />Transformer t=tf.newTransformer (); <br /><br /><br /><br />//设置XSLT引擎的属性(必不可少,否则会产生\\"汉字问题\\")。 <br /><br />Properties properties = t.getOutputProperties(); <br /><br />properties.setProperty(OutputKeys.ENCODING,"GB2312"); <br /><br />t.setOutputProperties(properties); <br /><br /><br /><br />//关键的一步, 调用Transformer对象 (XSLT引擎)的transform()方法,该方法的第一 <br /><br />//个参数是DOMSource对象,第二个参数是DOMResult对象。 <br /><br />t.transform(domSource,domResult); <br /><br /><br /><br />//创建缺省的Xalan XML Serializer,使用它将临时存放在DOMResult对象 <br /><br />//(domResult)中的内容以输出流的形式输出到输出介质中。 <br /><br />Serializer serializer = SerializerFactory.getSerializer <br /><br />(OutputProperties.getDefaultMethodProperties("xml")); <br /><br /><br /><br />//设置Xalan XML Serializer的输出属性,这一步必不可少,否则也可能产生 <br /><br />//所谓的"汉字问题\\"。 <br /><br />Properties prop=serializer.getOutputFormat(); <br /><br />prop.setProperty("encoding","GB2312"); <br /><br />serializer.setOutputFormat(prop); <br /><br /><br /><br />//创建一个File对象,代表DOM Tree所包含的数据的输出介质,这是一个XML文件。 <br /><br />File f = new File ("xuser3.xml"); <br /><br /><br /><br />//创建文件输出流对象fos,请留意构造函数的参数。 <br /><br />FileOutputStream fos=new FileOutputStream(f); <br /><br /><br /><br />//设置Xalan XML Serializer的输出流。 <br /><br />serializer.setOutputStream(fos); <br /><br /><br /><br />//串行化输出结果。 <br /><br />serializer.asDOMSerializer().serialize(domResult.getNode()); <br /><br />} <br /><br />catch (Exception tce) <br /><br />{ <br /><br />tce.printStackTrace(); <br /><br />} <br /><br /><br /><br /><br /><br /><br /><br />这个方法不太常用,而且似乎有点画蛇添足,所以我们就不展开讨论了。完整的例子请参考下列文件: AddRecord4.java(见附件)、user.xml(见附件)。该例子的运行环境为:Windows XP Professional、JDK 1.3.1。为了能够正常编译运行AddRecord4.java这个程序,你需要到网址http://xml.apache.org/dist/去下载安装Apache Xalan和Apache Xerces。 <br /><br /><br /><br />或者是到网址http://java.sun.com/xml/download.html去下载安装Java XML Pack。因为最新的Java XML Pack(Winter 01 版)包含了Apache Xalan和Apache Xerces技术在内。 <br /><br /><br /><br />结论: <br /><br /><br /><br />本文简略的讨论了Java语言编程中更新XML文档的四种方法。第一种方法是直接读写XML文件,这种方法十分繁琐,而且比较容易出错,极少使用,除非你需要开发自己的XML Parser,否则不会使用这种方法。第二种方法是使用Apache Crimson的XmlDocument类,这种方法极为简单,使用方便,如果你选用Apache Crimson作为XML解析器,那么不妨使用这种方法,不过这种方法似乎效率不高(源于效率低下的Apache Crimson),另外,高版本的JAXP或者是Java XML Pack、JWSDP不直接支持Apache Crimson,亦即这种方法不通用。第三种方法是使用JAXP的XSLT引擎(Transformer类)来输出XML文档,这种方法也许是标准的方法了,使用起来十分灵活,特别是可以自如控制输出格式,我们推荐采用这种方法。第四种方法是第三种方法的变种,采用了Xalan XML Serializer,引入了串行化操作,对于大量文档的修改/输出有优越性,可惜的是要重复设置XSLT引擎的属性和XML Serializer的输出属性,比较麻烦,而且依赖于Apache Xalan和Apache Xerces技术,通用性略显不足。 <br /><br /><br /><br />除了上面讨论的四种方法以外,实际上应用别的API(比如JDOM、Castor、XML4J、Oracle XML Parser V2)也有很多办法可以更新XML文档,限于篇幅,在这里就不一一讨论了。 <br /><br /><br /><br />参考文献以及资料来源: <br /><br /><br /><br />[1]The Java Web Services Tutorial, Sun Microsystems Inc. <br /><br /><br /><br />[2]http://xml.apache.org,Apache XML Project(Crimson、Xerces、Xalan) <br /><br /><br /><br />[3]http://www.jguru.com,XML Forum <br /><br /><br /><br />[4]http://forum.java.sun.com,Java Technology &amp; XML Forum <br /><img src ="http://www.blogjava.net/vso/aggbug/74808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 16:47 <a href="http://www.blogjava.net/vso/articles/74808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML入门常见问题(1)</title><link>http://www.blogjava.net/vso/articles/74744.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74744.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74744.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74744.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74744.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74744.html</trackback:ping><description><![CDATA[转载:<br /><a href="http://tech.ddvip.com/2006-04/11440049402881.html">http://tech.ddvip.com/2006-04/11440049402881.html</a><img src ="http://www.blogjava.net/vso/aggbug/74744.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 11:00 <a href="http://www.blogjava.net/vso/articles/74744.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML 编程思想:知识管理的基本 XML 和 RDF 技术(7)</title><link>http://www.blogjava.net/vso/articles/74742.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 02:58:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74742.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74742.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74742.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74742.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74742.html</trackback:ping><description><![CDATA[转载:<br /><a href="http://tech.ddvip.com/2006-08/11551014997207.html">http://tech.ddvip.com/2006-08/11551014997207.html</a><img src ="http://www.blogjava.net/vso/aggbug/74742.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 10:58 <a href="http://www.blogjava.net/vso/articles/74742.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从 XML 到 Java 代码的数据绑定（1）</title><link>http://www.blogjava.net/vso/articles/74735.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 02:54:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74735.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74735.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74735.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74735.html</trackback:ping><description><![CDATA[转载:<a href="http://tech.ddvip.com/2006-08/11551105717235.html"><br />http://tech.ddvip.com/2006-08/11551105717235.html</a><img src ="http://www.blogjava.net/vso/aggbug/74735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 10:54 <a href="http://www.blogjava.net/vso/articles/74735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML入门指南(11)XML解析器</title><link>http://www.blogjava.net/vso/articles/74732.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 02:46:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74732.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74732.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74732.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74732.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74732.html</trackback:ping><description><![CDATA[转载:<br /><a href="http://tech.ddvip.com/2006-04/11440139403001.html">http://tech.ddvip.com/2006-04/11440139403001.html</a><img src ="http://www.blogjava.net/vso/aggbug/74732.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 10:46 <a href="http://www.blogjava.net/vso/articles/74732.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML入门精解之结构与语法</title><link>http://www.blogjava.net/vso/articles/74731.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Thu, 12 Oct 2006 02:40:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74731.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74731.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74731.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74731.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74731.html</trackback:ping><description><![CDATA[转载:<br /><a href="http://tech.ddvip.com/2006-04/11440051202885.html">http://tech.ddvip.com/2006-04/11440051202885.html</a><img src ="http://www.blogjava.net/vso/aggbug/74731.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-12 10:40 <a href="http://www.blogjava.net/vso/articles/74731.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML信息集</title><link>http://www.blogjava.net/vso/articles/74486.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Wed, 11 Oct 2006 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74486.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74486.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74486.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74486.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74486.html</trackback:ping><description><![CDATA[
		<p>转载:<br /><a href="http://man.ddvip.com/web/xml_infoset/index.html">http://man.ddvip.com/web/xml_infoset/index.html</a></p>
<img src ="http://www.blogjava.net/vso/aggbug/74486.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-11 10:27 <a href="http://www.blogjava.net/vso/articles/74486.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML初学进阶</title><link>http://www.blogjava.net/vso/articles/74475.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Wed, 11 Oct 2006 02:21:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74475.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74475.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74475.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74475.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74475.html</trackback:ping><description><![CDATA[转载:<br /><a href="http://man.ddvip.com/web/xmljj/index.htm">http://man.ddvip.com/web/xmljj/index.htm</a><img src ="http://www.blogjava.net/vso/aggbug/74475.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-11 10:21 <a href="http://www.blogjava.net/vso/articles/74475.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML指南</title><link>http://www.blogjava.net/vso/articles/74470.html</link><dc:creator>vso</dc:creator><author>vso</author><pubDate>Wed, 11 Oct 2006 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/vso/articles/74470.html</guid><wfw:comment>http://www.blogjava.net/vso/comments/74470.html</wfw:comment><comments>http://www.blogjava.net/vso/articles/74470.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vso/comments/commentRss/74470.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vso/services/trackbacks/74470.html</trackback:ping><description><![CDATA[转载:<br /><a href="http://man.ddvip.com/web/xmlzhzn/xml_cn/default.asp.htm">http://man.ddvip.com/web/xmlzhzn/xml_cn/default.asp.htm</a><img src ="http://www.blogjava.net/vso/aggbug/74470.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vso/" target="_blank">vso</a> 2006-10-11 10:20 <a href="http://www.blogjava.net/vso/articles/74470.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>