JDOM使用详解及实例

[color=red]一、JDOM 简介[/color]

JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。

JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。

在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。
[color=red]二、JDOM 包概览[/color]

JDOM是由以下几个包组成的
[quote]org.jdom 包含了所有的xml文档要素的java类



org.jdom.adapters 包含了与dom适配的java类



org.jdom.filter 包含了xml文档的过滤器类



org.jdom.input 包含了读取xml文档的类



org.jdom.output 包含了写入xml文档的类



org.jdom.transform 包含了将jdom xml文档接口转换为其他xml文档接口



org.jdom.xpath 包含了对xml文档xpath操作的类三、JDOM 类说明[/quote]
[color=red]1、org.JDOM这个包里的类是你J解析xml文件后所要用到的所有数据类型。[/color]
[quote]Attribute

CDATA

Coment

DocType

Document

Element

EntityRef

Namespace

ProscessingInstruction

Text[/quote]

[color=red]2、org.JDOM.transform在涉及xslt格式转换时应使用下面的2个类[/color]

[quote]JDOMSource

JDOMResult

org.JDOM.input[/quote]
[color=red]
3、输入类,一般用于文档的创建工作[/color]
[quote]
SAXBuilder

DOMBuilder

ResultSetBuilder

org.JDOM.output[/quote]
[color=red]
4、输出类,用于文档转换输出[/color]
[quote]XMLOutputter

SAXOutputter

DomOutputter

JTreeOutputter[/quote]

[color=red]使用前注意事项:[/color]

1.JDOM对于JAXP 以及 TRax 的支持

JDOM 支持JAXP1.1:你可以在程序中使用任何的parser工具类,默认情况下是JAXP的parser。

制定特别的parser可用如下形式

SAXBuilder parser 

= new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl");

Document doc = parser.build("http://www.cafeconleche.org/");

// work with the document...

JDOM也支持TRaX:XSLT可通过JDOMSource以及JDOMResult类来转换(参见以后章节)

2.注意在JDOM里文档(Document)类由org.JDOM.Document 来表示。这要与org.w3c.dom中的Document区别开,这2种格式如何转换在后面会说明。

以下如无特指均指JDOM里的Document。
[color=red]四、JDOM主要使用方法[/color]

1.Ducument类

(1)Document的操作方法:

Element root = new Element("GREETING");

Document doc = new Document(root);

root.setText("Hello JDOM!");

或者简单的使用
Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t"));


这点和DOM不同。Dom则需要更为复杂的代码,如下:

DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();

DocumentBuilder builder =factory.newDocumentBuilder();

Document doc = builder.newDocument();

Element root =doc.createElement("root");

Text text = doc.createText("This is the root");

root.appendChild(text);

doc.appendChild(root);

[color=red]注意事项[/color]:JDOM不允许同一个节点同时被2个或多个文档相关联,要在第2个文档中使用原来老文档中的节点的话。首先需要使用detach()把这个节点分开来。
[color=red](2)从文件、流、系统IO、URL得到Document对象:[/color]


DOMBuilder builder = new DOMBuilder();

Document doc = builder.build(new File("jdom_test.xml"));

SAXBuilder builder = new SAXBuilder();

Document doc = builder.build(url);


在新版本中DOMBuilder 已经Deprecated掉 DOMBuilder.builder(url),用SAX效率会比较快。

这里举一个小例子,为了简单起见,使用String对象直接作为xml数据源:

public jdomTest() {

String textXml = null;

textXml = "<note>";

textXml = textXml +

"<to>aaa</to><from>bbb</from><heading>ccc</heading><body>ddd</body>";

textXml = textXml + "</note>";

SAXBuilder builder = new SAXBuilder();

Document doc = null;

Reader in= new StringReader(textXml);

try {

doc = builder.build(in);

Element root = doc.getRootElement();

List ls = root.getChildren();//注意此处取出的是root节点下面的一层的Element集合

for (Iterator iter = ls.iterator(); iter.hasNext(); ) {

Element el = (Element) iter.next();

if(el.getName().equals("to")){

System.out.println(el.getText());

}

}

}

catch (IOException ex) {

ex.printStackTrace();

}

catch (JDOMException ex) {

ex.printStackTrace();

}

}


[color=red](3)DOM的document和JDOM的Document之间的相互转换使用方法,简单![/color]

DOMBuilder builder = new DOMBuilder();

org.jdom.Document jdomDocument = builder.build(domDocument);

DOMOutputter converter = new DOMOutputter();// work with the JDOM document…

org.w3c.dom.Document domDocument = converter.output(jdomDocument);

// work with the DOM document…

[color=red]

2.XML文档输出[/color]

XMLOutPutter类:

JDOM的输出非常灵活,支持很多种io格式以及风格的输出

Document doc = new Document(...);

XMLOutputter outp = new XMLOutputter();

outp.output(doc, fileOutputStream); // Raw output

outp.setTextTrim(true); // Compressed output

outp.output(doc, socket.getOutputStream());

outp.setIndent(" ");// Pretty output

outp.setNewlines(true);

outp.output(doc, System.out);

详细请参阅最新的JDOM API手册

3.Element 类:

(1)浏览Element树

Element root = doc.getRootElement();//获得根元素element

List allChildren = root.getChildren();// 获得所有子元素的一个list

List namedChildren = root.getChildren("name");// 获得指定名称子元素的list

Element child = root.getChild("name");//获得指定名称的第一个子元素

JDOM给了我们很多很灵活的使用方法来管理子元素(这里的List是java.util.List)

List allChildren = root.getChildren();

allChildren.remove(3); // 删除第四个子元素

allChildren.removeAll(root.getChildren("jack"));// 删除叫“jack”的子元素

root.removeChildren("jack"); // 便捷写法

allChildren.add(new Element("jane"));// 加入

root.addContent(new Element("jane")); // 便捷写法

allChildren.add(0, new Element("first"));

(2)移动Elements:

在JDOM里很简单

Element movable = new Element("movable");

parent1.addContent(movable); // place

parent1.removeContent(movable); // remove

parent2.addContent(movable); // add

在Dom里

Element movable = doc1.createElement("movable");

parent1.appendChild(movable); // place

parent1.removeChild(movable); // remove

parent2.appendChild(movable); // 出错!

补充:纠错性

JDOM的Element构造函数(以及它的其他函数)会检查element是否合法。

而它的add/remove方法会检查树结构,检查内容如下:

[quote]1.在任何树中是否有回环节点

2.是否只有一个根节点

3.是否有一致的命名空间(Namespaces)[/quote]

(3)Element的text内容读取

<description>

A cool demo

</description>

// The text is directly available

// Returns "\n A cool demo\n"

String desc = element.getText();

// There's a convenient shortcut

// Returns "A cool demo"

String desc = element.getTextTrim();

(4)Elment内容修改

element.setText("A new description");

3.可正确解释特殊字符

element.setText("<xml> content");

4.CDATA的数据写入、读出

element.addContent(new CDATA("<xml> content"));

String noDifference = element.getText();

混合内容

element可能包含很多种内容,比如说

[quote]<table>

<!-- Some comment -->

Some text

<tr>Some child element</tr>

</table>[/quote]
取table的子元素tr

String text = table.getTextTrim();

Element tr = table.getChild("tr");

也可使用另外一个比较简单的方法

List mixedCo = table.getContent();

Iterator itr = mixedCo.iterator();

while (itr.hasNext()) {

Object o = i.next();

if (o instanceof Comment) {...}

// 这里可以写成Comment, Element, Text, CDATA,ProcessingInstruction, 或者是EntityRef的类型

}

// 现在移除Comment,注意这里游标应为1。这是由于回车键也被解析成Text类的缘故,所以Comment项应为1。

mixedCo.remove(1);

4.Attribute类

<table width="100%" border="0"> </table>

String width = table.getAttributeValue("width");//获得attribute

int border = table.getAttribute("width").getIntValue();

table.setAttribute("vspace", "0");//设置attribute

table.removeAttribute("vspace");// 删除一个或全部attribute

table.getAttributes().clear();


5.处理指令(Processing Instructions)操作

一个Pls的例子

<?br?>

<?cocoon-process type="xslt"?>

| |

| |

目标 数据

处理目标名称(Target)

String target = pi.getTarget();

获得所有数据(data),在目标(target)以后的所有数据都会被返回。

String data = pi.getData();

String type = pi.getValue("type");获得指定属性的数据

List ls = pi.getNames();获得所有属性的名称


6.命名空间操作

<xhtml:html 

xmlns:xhtml="http://www.w3.org/1999/xhtml">

<xhtml:title>Home Page</xhtml:title>

</xhtml:html>

Namespace xhtml = Namespace.getNamespace("xhtml", "http://www.w3.org/1999/xhtml");

List kids = html.getChildren("title", xhtml);

Element kid = html.getChild("title", xhtml);

kid.addContent(new Element("table", xhtml));


7.XSLT格式转换

使用以下函数可对XSLT转换

最后如果你需要使用w3c的Document则需要转换一下。

public static Document transform(String stylesheet,Document in)

throws JDOMException {

try {

Transformer transformer = TransformerFactory.newInstance()

.newTransformer(new StreamSource(stylesheet));

JDOMResult out = new JDOMResult();

transformer.transform(new JDOMSource(in), out);

return out.getDeocument();

}

catch (TransformerException e) {

throw new JDOMException("XSLT Trandformation failed", e);

}

}


[color=red]
五、用例:[/color]

1、生成xml文档:





public class WriteXML{

public void BuildXML() throws Exception {

Element root,student,number,name,age;

root = new Element("student-info"); //生成根元素:student-info

student = new Element("student"); //生成元素:student(number,name,age)

number = new Element("number");

name = new Element("name");

age = new Element("age");

Document doc = new Document(root); //将根元素植入文档doc中

number.setText("001");

name.setText("lnman");

age.setText("24");

student.addContent(number);

student.addContent(name);

student.addContent(age);

root.addContent(student);

Format format = Format.getCompactFormat();

format.setEncoding("gb2312"); //设置xml文件的字符为gb2312

format.setIndent(" "); //设置xml文件的缩进为4个空格

XMLOutputter XMLOut = new XMLOutputter(format);//元素后换行一层元素缩四格

XMLOut.output(doc, new FileOutputStream("studentinfo.xml"));

}

public static void main(String[] args) throws Exception {

WriteXML w = new WriteXML();

System.out.println("Now we build an XML document .....");

w.BuildXML();

System.out.println("finished!");

}

}
生成的xml文档为:

[quote]<?xml version="1.0" encoding="gb2312"?>

<student-info>

<student>

<number>001</number>

<name>lnman</name>

<age>24</age>

</student>

</student-info>[/quote]

创建XML文档2:

 public class CreateXML {

public void Create() {

try {

Document doc = new Document();

ProcessingInstruction pi=new ProcessingInstruction("xml-stylesheet","type="text/xsl" href="test.xsl"");

doc.addContent(pi);

Namespace ns = Namespace.getNamespace("http://www.bromon.org" );

Namespace ns2 = Namespace.getNamespace("other", "http://www.w3c.org" );

Element root = new Element("根元素", ns);

root.addNamespaceDeclaration(ns2);

doc.setRootElement(root);

Element el1 = new Element("元素一");

el1.setAttribute("属性", "属性一");

Text text1=new Text("元素值");

Element em = new Element("元素二").addContent("第二个元素");

el1.addContent(text1);

el1.addContent(em);

Element el2 = new Element("元素三").addContent("第三个元素");

root.addContent(el1);

root.addContent(el2);

//缩进四个空格,自动换行,gb2312编码

XMLOutputter outputter = new XMLOutputter(" ", true,"GB2312");

outputter.output(doc, new FileWriter("test.xml"));

}catch(Exception e) {

System.out.println(e);

}

}

public static void main(String args[]) {

new CreateXML().Create();

}

}

2、读取xml文档的例子:

import org.jdom.output.*;

import org.jdom.input.*;

import org.jdom.*;

import java.io.*;

import java.util.*;

public class ReadXML{

public static void main(String[] args) throws Exception {

SAXBuilder builder = new SAXBuilder();

Document read_doc = builder.build("studentinfo.xml");

Element stu = read_doc.getRootElement();

List list = stu.getChildren("student");

for(int i = 0;i < list.size();i++) {

Element e = (Element)list.get(i);

String str_number = e.getChildText("number");

String str_name = e.getChildText("name");

String str_age = e.getChildText("age");

System.out.println("---------STUDENT--------------");

System.out.println("NUMBER:" + str_number);

System.out.println("NAME:" + str_name);

System.out.println("AGE:" + str_age);

System.out.println("------------------------------");

System.out.println();

}

}

}

3、DTD验证的:

public class XMLWithDTD {

public void validate() {

try {

SAXBuilder builder = new SAXBuilder(true);

builder.setFeature("http://xml.org/sax/features/validation";,true);

Document doc = builder.build(new FileReader("author.xml"));

System.out.println("搞掂");

XMLOutputter outputter = new XMLOutputter();

outputter.output(doc, System.out);

}catch(Exception e) {

System.out.println(e);

}

}

public static void main(String args[]) {

new XMLWithDTD().validate();

}

}


  需要说明的是,这个程序没有指明使用哪个DTD文件。DTD文件的位置是在XML中指定的,而且DTD不支持命名空间,一个XML只能引用一个DTD,所以程序直接读取XML中指定的DTD,程序本身不用指定。不过这样一来,好象就只能使用外部式的DTD引用方式了?高人指点。

4、XML Schema验证的:

 public class XMLWithSchema {

String xml="test.xml";

String schema="test-schema.xml";

public void validate() {

try {

SAXBuilder builder = new SAXBuilder(true);

//指定约束方式为XML schema

builder.setFeature("http://apache.org/xml/features/validation/schema";, true);

//导入schema文件

builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";,schema);

Document doc = builder.build(new FileReader(xml));

System.out.println("搞掂");

XMLOutputter outputter = new XMLOutputter();

outputter.output(doc, System.out);

}catch(Exception e) {

System.out.println("验证失败:"+e);

}

}

}


上面的程序就指出了要引入的XML Schema文件的位置。

系统默认输出是UTF-8,这有可能导致出现乱码。
[color=red]
5、Xpath例子:[/color]

JDOM的关于XPATH的api在org.jdom.xpath这个包里。这个包下,有一个抽象类XPath.java和实现类JaxenXPath.java, 使用时先用XPath类的静态方法newInstance(String xpath)得到XPath对象,然后调用它的selectNodes(Object context)方法或selectSingleNode(Object context)方法,前者根据xpath语句返回一组节点(List对象);后者根据一个xpath语句返回符合条件的第一个节点(Object类型)。请看jdom-1.0自带的范例程序:

它分析在web.xml文件中的注册的servlet的个数及参数个数,并输出角色名。

web.xml文件:

<[quote]?xml version="1.0" encoding="ISO-8859-1"?>

<!--

<!DOCTYPE web-app

PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"

"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">

-->

<web-app>

<servlet>

<servlet-name>snoop</servlet-name>

<servlet-class>SnoopServlet</servlet-class>

</servlet>

<servlet>

<servlet-name>file </servlet-name>

<servlet-class>ViewFile</servlet-class>

<init-param>

<param-name>initial</param-name>

<param-value>1000</param-value>

<description>The initial value for the counter <!-- optional --></description>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>mv</servlet-name>

<url-pattern>*.wm</url-pattern>

</servlet-mapping>

<distributed/>

<security-role>

<role-name>manager</role-name>

<role-name>director</role-name>

<role-name>president</role-name>

</security-role>

</web-app> [/quote]


处理程序:

import java.io.*; 

import java.util.*;

public class XPathReader {

public static void main(String[] args) throws IOException, JDOMException {

if (args.length != 1) {

System.err.println("Usage: java XPathReader web.xml");

return;

}

String filename = args[0];//从命令行输入web.xml

PrintStream out = System.out;

SAXBuilder builder = new SAXBuilder();

Document doc = builder.build(new File(filename));//得到Document对象





// Print servlet information

XPath servletPath = XPath.newInstance("//servlet");//,选择任意路径下servlet元素

List servlets = servletPath.selectNodes(doc);//返回所有的servlet元素。

out.println("This WAR has "+ servlets.size() +" registered servlets:");

Iterator i = servlets.iterator();

while (i.hasNext()) {//输出servlet信息

Element servlet = (Element) i.next();

out.print("\t" + servlet.getChild("servlet-name")

.getTextTrim() +

" for " + servlet.getChild("servlet-class")

.getTextTrim());

List initParams = servlet.getChildren("init-param");

out.println(" (it has " + initParams.size() + " init params)");

}

// Print security role information

XPath rolePath = XPath.newInstance("//security-role/role-name/text()");

List roleNames = rolePath.selectNodes(doc);//得到所有的角色名

if (roleNames.size() == 0) {

out.println("This WAR contains no roles");

} else {

out.println("This WAR contains " + roleNames.size() + " roles:");

i = roleNames.iterator();

while (i.hasNext()) {//输出角色名

out.println("\t" + ((Text)i.next()).getTextTrim());

}

}

}

}


输出结果:
[quote]
C:\java>java XPathReader web.xml

This WAR has 2 registered servlets:

snoop for SnoopServlet (it has 0 init params)

file for ViewFile (it has 1 init params)

This WAR contains 3 roles:

manager

director

president[/quote]


6、数据输入要用到XML文档要通过org.jdom.input包,反过来需要org.jdom.output。如前面所说,关是看API文档就能够使用。

我们的例子读入XML文件exampleA.xml,加入一条处理指令,修改第一本书的价格和作者,并添加一条属性,然后写入文件exampleB.xml:

[quote]//exampleA.xml

<?xml version="1.0" encoding="GBK"?>

<bookList>

<book>

<name>Java编程入门</name>

<author>张三</author>

<publishDate>2002-6-6</publishDate>

<price>35.0</price>

</book>

<book>

<name>XML在Java中的应用</name>

<author>李四</author>

<publishDate>2002-9-16</publishDate>

<price>92.0</price>

</book>

</bookList> [/quote]

//testJDOM.java 

import org.jdom.*;

import org.jdom.output.*;

import org.jdom.input.*;

import java.io.*;

public class TestJDOM{

public static void main(String args[])throws Exception{

SAXBuilder sb = new SAXBuilder();

//从文件构造一个Document,因为XML文件中已经指定了编码,所以这里不必了

Document doc = sb.build(new FileInputStream("exampleA.xml"));

ProcessingInstruction pi = new ProcessingInstruction//加入一条处理指令

("xml-stylesheet","href=\"bookList.html.xsl\" type=\"text/xsl\"");

doc.addContent(pi);

Element root = doc.getRootElement(); //得到根元素

java.util.List books = root.getChildren(); //得到根元素所有子元素的集合

Element book = (Element)books.get(0); //得到第一个book元素

//为第一本书添加一条属性

Attribute a = new Attribute("hot","true");

book.setAttribute(a);

Element author = book.getChild("author"); //得到指定的字元素

author.setText("王五"); //将作者改为王五

//或 Text t = new Text("王五");book.addContent(t);

Element price = book.getChild("price"); //得到指定的字元素

//修改价格,比较郁闷的是我们必须自己转换数据类型,而这正是JAXB的优势

author.setText(Float.toString(50.0f));

String indent = " ";

boolean newLines = true;

XMLOutputter outp = new XMLOutputter(indent,newLines,"GBK");

outp.output(doc, new FileOutputStream("exampleB.xml"));

}

};



执行结果exampleB.xml:

[quote]<?xml version="1.0" encoding="GBK"?>

<bookList>

<book hot=”true”>

<name>Java编程入门</name>

<author>50.0</author>

<publishDate>2002-6-6</publishDate>

<price>35.0</price>

</book>

<book>

<name>XML在Java中的应用</name>

<author>李四</author>

<publishDate>2002-9-16</publishDate>

<price>92.0</price>

</book>

</bookList>

<?xml-stylesheet href="bookList.html.xsl" type="text/xsl"?> [/quote]

在默认情况下,JDOM的Element类的getText()这类的方法不会过滤空白字符,如果你需要过滤,用setTextTrim() 。

文章转自:[url]http://www.webdn.com/web_file/3sword/xml/0602016011/[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值