??xml version="1.0" encoding="utf-8" standalone="yes"?>精品亚洲欧美一区,777精品伊人久久久久大香线蕉,国内精品伊人久久http://www.aygfsteel.com/zhangrenquan/category/13499.htmlzh-cnWed, 28 Feb 2007 05:09:23 GMTWed, 28 Feb 2007 05:09:23 GMT60java操作xml摘录(dom)http://www.aygfsteel.com/zhangrenquan/articles/60384.htmlkelvenkelvenThu, 27 Jul 2006 09:06:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/60384.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/60384.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/60384.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/60384.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/60384.html
下面我们来看一个简单的例子Q看看在DOM中,我们是如何来操作一个XML文档的?

q是一个XML文档Q也是我们要操作的对象:



Good-bye serialization, hello Java!
BR>
下面Q我们需要把q个文档的内容解析到一个个的Java对象中去供程序用,利用JAXPQ我们只需几行代码p做到q一炏V首先,我们需要徏立一个解析器工厂Q以利用q个工厂来获得一个具体的解析器对象:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

我们在这里用DocumentBuilderFacotry的目的是Z创徏与具体解析器无关的程序,当DocumentBuilderFactorycȝ静态方法newInstance()被调用时Q它Ҏ一个系l变量来军_具体使用哪一个解析器。又因ؓ所有的解析器都服从于JAXP所定义的接口,所以无论具体用哪一个解析器Q代码都是一L。所以当在不同的解析器之间进行切换时Q只需要更改系l变量的|而不用更改Q何代码。这是工厂所带来的好处。这个工厂模式的具体实现Q可以参看下面的cd?

DocumentBuilder db = dbf.newDocumentBuilder();

当获得一个工厂对象后Q用它的静态方法newDocumentBuilder()Ҏ可以获得一个DocumentBuilder对象Q这个对象代表了具体的DOM解析器。但具体是哪一U解析器Q微软的或者IBM的,对于E序而言q不重要?

然后Q我们就可以利用q个解析器来对XML文档q行解析了:

Document doc = db.parse("c:/xml/message.xml");

DocumentBuilder的parse()Ҏ接受一个XML文档名作入参敎ͼq回一个Document对象Q这个Document对象׃表了一个XML文档的树模型。以后所有的对XML文档的操作,都与解析器无养I直接在这个Document对象上进行操作就可以了。而具体对Document操作的方法,是由DOM所定义的了?

Jaxp支持W3C所推荐的DOM 2。如果你对DOM很熟悉,那么下面的内容就很简单了Q只需要按照DOM的规范来q行Ҏ调用可以。当Ӟ如果你对DOM不清楚,也不用着急,后面我们会有详细的介l。在q儿Q你所要知道ƈ牢记的是QDOM是用来描叙XML文档中的数据的模型,引入DOM的全部原因就是ؓ了用q个模型来操作XML文档的中的数据。DOM规范中定义有节点Q即对象Q、属性和ҎQ我们通过q些节点的存取来存取XML的数据?

从上面得到的Document对象开始,我们可以开始我们的DOM之旅了。用Document对象的getElementsByTagName()ҎQ我们可以得C个NodeList对象Q一个Node对象代表了一个XML文档中的一个标{օ素,而NodeList对象Q观其名而知其意Q所代表的是一个Node对象的列表:

NodeList nl = doc.getElementsByTagName("message");

我们通过q样一条语句所得到的是XML文档中所?message />标签对应的Node对象的一个列表。然后,我们可以使用NodeList对象的item()Ҏ来得到列表中的每一个Node对象Q?

Node my_node = nl.item(0);

当一个Node对象被徏立之后,保存在XML文档中的数据p提取出来q封装在q个Node中了。在q个例子中,要提取Message标签内的内容Q我们通常会用Node对象的getNodeValue()ҎQ?

String message = my_node.getFirstChild().getNodeValue();

h意,q里q用了一个getFirstChild()Ҏ来获得message下面的第一个子Node对象。虽然在message标签下面除了文本外ƈ没有其它子标{或者属性,但是我们坚持在这里用getFirseChild()ҎQ这主要和W3C对DOM的定义有兟뀂W3C把标{ֆ的文本部分也定义成一个NodeQ所以先要得C表文本的那个NodeQ我们才能够使用getNodeValue()来获取文本的内容?

现在Q既然我们已l能够从XML文g中提取出数据了,我们可以把q些数据用在合适的地方Q来构筑应用E序?

下面的内容,我们更多的xDOMQؓDOM作一个较l的解析Q我们使用h更ؓ得心应手?

1Q基本的DOM对象

DOM的基本对象有5个:DocumentQNodeQNodeListQElement和Attr。下面就q些对象的功能和实现的方法作一个大致的介绍?

Document对象代表了整个XML的文档,所有其它的NodeQ都以一定的序包含在Document对象之内Q排列成一个树形的l构Q程序员可以通过遍历q颗树来得到XML文档的所有的内容Q这也是对XML文档操作的v炏V我们L先通过解析XML源文件而得C个Document对象Q然后再来执行后l的操作。此外,Documentq包含了创徏其它节点的方法,比如createAttribut()用来创徏一个Attr对象。它所包含的主要的Ҏ有:

createAttribute(String)Q用l定的属性名创徏一个Attr对象Qƈ可在其后使用setAttributeNodeҎ来放|在某一个Element对象上面?

createElement(String)Q用l定的标{֐创徏一个Element对象Q代表XML文档中的一个标{,然后可以在q个Element对象上添加属性或q行其它的操作?

createTextNode(String)Q用l定的字W串创徏一个Text对象QText对象代表了标{或者属性中所包含的纯文本字符丌Ӏ如果在一个标{ֆ没有其它的标{,那么标签内的文本所代表的Text对象是这个Element对象的唯一子对象?

getElementsByTagName(String)Q返回一个NodeList对象Q它包含了所有给定标{֐字的标签?

getDocumentElement()Q返回一个代表这个DOM树的根节点的Element对象Q也是代表XML文档根元素的那个对象?

Node对象是DOMl构中最为基本的对象Q代表了文档树中的一个抽象的节点。在实际使用的时候,很少会真正的用到Nodeq个对象Q而是用到诸如Element、Attr、Text{Node对象的子对象来操作文档。Node对象些对象提供了一个抽象的、公q栏V虽然在Node对象中定义了对其子节点进行存取的ҎQ但是有一些Node子对象,比如Text对象Q它q不存在子节点,q一Ҏ要注意的。Node对象所包含的主要的Ҏ有:

appendChild(org.w3c.dom.Node)Qؓq个节点d一个子节点Qƈ攑֜所有子节点的最后,如果q个子节点已l存在,则先把它删掉再添加进厅R?

getFirstChild()Q如果节点存在子节点Q则q回W一个子节点Q对{的Q还有getLastChild()Ҏq回最后一个子节点?

getNextSibling()Q返回在DOM树中q个节点的下一个兄弟节点,对等的,q有getPreviousSibling()Ҏq回其前一个兄弟节炏V?

getNodeName()Q根据节点的cdq回节点的名U?

getNodeType()Q返回节点的cd?

getNodeValue()Q返回节点的倹{?

hasChildNodes()Q判断是不是存在有子节点?

hasAttributes()Q判断这个节Ҏ否存在有属性?

getOwnerDocument()Q返回节Ҏ处的Document对象?

insertBefore(org.w3c.dom.Node newQorg.w3c.dom.Node ref)Q在l定的一个子对象前再插入一个子对象?

removeChild(org.w3c.dom.Node)Q删除给定的子节点对象?

replaceChild(org.w3c.dom.Node newQorg.w3c.dom.Node old)Q用一个新的Node对象代替l定的子节点对象?

NodeList对象Q顾名思义Q就是代表了一个包含了一个或者多个Node的列表。可以简单的把它看成一个Node的数l,我们可以通过Ҏ来获得列表中的元素:

GetLength()Q返回列表的长度?

Item(int)Q返回指定位|的Node对象?

Element对象代表的是XML文档中的标签元素Q承于NodeQ亦是Node的最主要的子对象。在标签中可以包含有属性,因而Element对象中有存取其属性的ҎQ而Q何Node中定义的ҎQ也可以用在Element对象上面?

getElementsByTagName(String)Q返回一个NodeList对象Q它包含了在q个标签中其下的子孙节点中具有给定标{֐字的标签?

getTagName()Q返回一个代表这个标{֐字的字符丌Ӏ?

getAttribute(String)Q返回标{中l定属性名U的属性的倹{在q儿需要主要的是,应ؓXML文档中允许有实体属性出玎ͼ而这个方法对q些实体属性ƈ不适用。这时候需要用到getAttributeNodes()Ҏ来得C个Attr对象来进行进一步的操作?

getAttributeNode(String)Q返回一个代表给定属性名U的Attr对象?

Attr对象代表了某个标{中的属性。Attrl承于NodeQ但是因为Attr实际上是包含在Element中的Q它q不能被看作是Element的子对象Q因而在DOM中Attrq不是DOM树的一部分Q所以Node中的getparentNode()QgetpreviousSibling()和getnextSibling()q回的都是null。也是_Attr其实是被看作包含它的Element对象的一部分Q它q不作ؓDOM树中单独的一个节点出现。这一点在使用的时候要同其它的Node子对象相区别?

需要说明的是,上面所说的DOM对象在DOM中都是用接口定义的,在定义的时候用的是与具体语言无关的IDL语言来定义的。因而,DOM其实可以在Q何面向对象的语言中实玎ͼ只要它实CDOM所定义的接口和功能可以了。同Ӟ有些Ҏ在DOM中ƈ没有定义Q是用IDL的属性来表达的,当被映射到具体的语言Ӟq些属性被映射为相应的Ҏ?

· 2QDOM实例

有了上面的介l,怿你对DOM理解的更多了吧。下面的例子让你对DOM更加熟悉h?

先说说这个例子到底要做的是什么吧Q我们希望在一个名为link.xml文g中保存了一些URL地址Q通过一个简单的E序Q我们可以通过DOM把这些URLdq显C出来,也可以反q来向这个XML文g中写入加入的URL地址。很单,却很实用Q也_来例CDOM的绝大部分用法了?

XML文g本n不复杂,׃l出它的DTD了。link.xml:



<pre>
<?xml version="1.0" standalone="yes"?>
<links>
<link>
<text>JSP Insider</text>
<url newWindow="no"> ;http://www.jspinsider.com< ;/url>
<author>JSP Insider</author>
<date>
<day>2</day>
<month>1</month>
<year>2001</year>
</date>
<description>A JSP information site.</description>
</link>
<link>
<text>The makers of Java</text>
<url newWindow="no"> ;http://java.sun.com< ;/url>
<author>Sun Microsystems</author>
<date>
<day>3</day>
<month>1</month>
<year>2001</year>
</date>
<description>Sun Microsystem´s website.</description>
</link>
<link>
<text>The standard JSP container</text>
<url newWindow="no"> ;http://jakarta.apache.org< ;/url>
<author>Apache Group</author>
<date>
<day>4</day>
<month>1</month>
<year>2001</year>
</date>
<description>Some great software.</description>
</link>
</links>
BR></pre>
W一个程序我们称为xmldisplay.javaQ具体的E序清单可以在附件中扑ֈ。主要的功能是dq个XML文g中各个节点的内容Q然后在格式化输出在System.out上,我们来看看这个程序:
import javax.xml.parsers.*;
import org.w3c.dom.*;

q是引入必要的类Q因为在q里使用的是Sun所提供的XML解析器,因而需要引入java.xml.parsers包,其中包含了有DOM解析器和SAX解析器的具体实现。org.w3c.dom包中定义了w3c所制定的DOM接口?

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc=builder.parse("links.xml");
doc.normalize();

除了上面讲到的,q有一个小技巧,对Document对象调用normalize()Q可以去掉XML文档中作为格式化内容的空白而映在DOM树中的不必要的Text Node对象。否则你得到的DOM树可能ƈ不如你所惌的那栗特别是在输出的时候,q个normalize()更ؓ有用?

NodeList links =doc.getElementsByTagName("link");

刚才说过QXML文档中的I白W也会被作ؓ对象映射在DOM树中。因而,直接调用NodeҎ的getChildNodesҎ有时候会有些问题Q有时不能够q回所期望的NodeList对象。解决的办法是用Element的getElementByTagName(String)Q返回的NodeLise是所期待的对象了。然后,可以用item()Ҏ提取惌的元素?

for (int i=0;i
Element link=(Element) links.item(i);
System.out.print("Content: ");
System.out.println(link.getElementsByTagName("text").item(0).getFirstChild().getNodeValue());
System.out.print("URL: ");
System.out.println(link.getElementsByTagName("url").item(0).getFirstChild().getNodeValue());

System.out.print("Author: ");
System.out.println(link.getElementsByTagName("author").item(0).getFirstChild().getNodeValue());
System.out.print("Date: ");
Element linkdate=(Element) link.getElementsByTagName("date").item(0);
String day=linkdate.getElementsByTagName("day").item(0).getFirstChild().getNodeValue();
String month=linkdate.getElementsByTagName("month").item(0).getFirstChild().getNodeValue();
String year=linkdate.getElementsByTagName("year").item(0).getFirstChild().getNodeValue();
System.out.println(day+"-"+month+"-"+year);
System.out.print("Description: ");
System.out.println(link.getElementsByTagName("description").item(0).getFirstChild().getNodeValue());
System.out.println();
}

上面的代码片断就完成了对XML文档内容的格式化输出。只要注意到一些细节的问题Q比如getFirstChile()Ҏ和getElementsByTagName()Ҏ的用,q些q是比较Ҏ的?

下面的内容,是在修改了DOM树后重新写入到XML文档中去的问题了。这个程序名为xmlwrite.java。在JAXP1.0版本中,q没有直接的cdҎ能够处理XML文档的写入问题,需要借助其它包中的一些辅助类。而在JAXP1.1版本中,引入了对XSLT的支持,所谓XSLTQ就是对XML文档q行变换QTranslationQ后Q得C个新的文档结构。利用这个新加入的功能,我们p够很方便的把新生成或者修改后的DOM树从新写回到XML文g中去了,下面我们来看看代码的实现Q这D代码的主要功能是向links.xml文g中加入一个新的link节点Q?

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;

新引入的java.xml.transform包中的几个类Q就是用来处理XSLT变换的?

我们希望在上面的XML文g中加入一个新的link节点Q因而首先还是要dlinks.xml文gQ构Z个DOM树,然后再对q个DOM树进行修改(d节点Q,最后把修改后的DOM写回到links.xml文g中:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc=builder.parse("links.xml");
doc.normalize();
//---取得变量----
String text="Hanzhong´s Homepage";
String url="www.hzliu.com";
String author="Hzliu Liu";
String discription="A site from Hanzhong Liu, give u lots of suprise!!!";

Z看清重点Q简化程序,我们把要加入的内容硬~码到记忆String对象中,而实际操作中Q往往利用一个界面来提取用户输入Q或者通过JDBC从数据库中提取想要的内容?

Text textseg;
Element link=doc.createElement("link");

首先应该明了的是Q无Z么类型的NodeQText型的也好QAttr型的也好QElement型的也好Q它们的创徏都是通过Document对象中的createXXX()Ҏ来创建的QXXX代表具体要创建的cdQ,因此Q我们要向XML文档中添加一个link目Q首先要创徏一个link对象Q?

Element linktext=doc.createElement("text");
textseg=doc.createTextNode(text);
linktext.appendChild(textseg);
link.appendChild(linktext);
Element linkurl=doc.createElement("url");
textseg=doc.createTextNode(url);
linkurl.appendChild(textseg);
link.appendChild(linkurl);
Element linkauthor=doc.createElement("author");
textseg=doc.createTextNode(author);
linkauthor.appendChild(textseg);
link.appendChild(linkauthor);
java.util.Calendar rightNow = java.util.Calendar.getInstance();
String day=Integer.toString(rightNow.get(java.util.Calendar.DAY_OF_MONTH));
String month=Integer.toString(rightNow.get(java.util.Calendar.MONTH));

String year=Integer.toString(rightNow.get(java.util.Calendar.YEAR));
Element linkdate=doc.createElement("date");
Element linkdateday=doc.createElement("day");
textseg=doc.createTextNode(day);
linkdateday.appendChild(textseg);
Element linkdatemonth=doc.createElement("month");
textseg=doc.createTextNode(month);
linkdatemonth.appendChild(textseg);
Element linkdateyear=doc.createElement("year");
textseg=doc.createTextNode(year);
linkdateyear.appendChild(textseg);
linkdate.appendChild(linkdateday);
linkdate.appendChild(linkdatemonth);
linkdate.appendChild(linkdateyear);
link.appendChild(linkdate);
Element linkdiscription=doc.createElement("description");
textseg=doc.createTextNode(discription);
linkdiscription.appendChild(textseg);
link.appendChild(linkdiscription);

创徏节点的过E可能有些千一律,但需要注意的地方是,对Element中所包含的textQ在DOM中,q些text也是代表了一个Node的,因此也必Mؓ它们创徏相应的nodeQ,不能直接用Element对象的setNodeValue()Ҏ来设|这些text的内容,而需要用创徏的Text对象的setNodeValue()Ҏ来设|文本,q样才能够把创徏的Element和其文本内容d到DOM树中。看看前面的代码Q你会更好的理解q一点:

doc.getDocumentElement().appendChild(link);

最后,不要忘记把创建好的节Ҏ加到DOM树中。DocumentcȝgetDocumentElement()ҎQ返回代表文档根节点的Element对象。在XML文档中,根节点一定是唯一的?

TransformerFactory tFactory =TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new java.io.File("links.xml"));
transformer.transform(source, result);

然后是用XSLT把DOM树输Z。这里的TransformerFactory也同样应用了工厂模式Q得具体的代码同具体的变换器无兟뀂实现的Ҏ和DocumentBuilderFactory相同Q这儿就不赘qC。TransformercȝtransfromҎ接受两个参数、一个数据源Source和一个输出目标Result。这里分别用的是DOMSource和StreamResultQ这样就能够把DOM的内容输出到一个输出流中,当这个输出流是一个文件的时候,DOM的内容就被写入到文g中去了?br />



kelven 2006-07-27 17:06 发表评论
]]>
վ֩ģ壺 Ǩ| | | | ¡| | Ǽ| ̨| غ| ˷| ¡| ɽ| | ɽ| ÷| ƽ| żҿ| ˮ| | | | Դ| | | | | | | | | | | Զ| | º| ƽ| ̨| Ͱ| ƽ| | |