JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。
JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。
在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。
JDOM 在2000年的春天被Brett McLaughlin和Jason Hunter开发出来,以弥补DOM及SAX在实际应用当中的不足之处。这些不足之处主要在于SAX没有文档修改、随机访问以及输出的功能,而对于DOM来说,JAVA程序员在使用时来用起来总觉得不太方便。DOM的缺点主要是来自于由于Dom是一个接口定义语言(IDL),它的任务是在不同语言实现中的一 个最低的通用标准,并不是为JAVA特别设计的。JDOM的最新版本为JDOM Beta 9。最近JDOM被收录到JSR-102内,这标志着JDOM成为了JAVA平台组成的一部分。
maven结构:
<dependency> <groupId>org.jdom</groupId> <artifactId>jdom</artifactId> <version>1.1</version>
Attribute CDATA Coment DocType Document Element EntityRef Namespace ProscessingInstruction Text
SAXBuilder
DOMBuilder
ResultSetBuilder
4、org.JDOM.output输出类,用于文档转换输出
XMLOutputter
SAXOutputter
DomOutputter
JTreeOutputter
使用前注意事项:
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...
2.注意在JDOM里文档(Document)类由org.JDOM.Document 来表示。这要与org.w3c.dom中的Document区别开,这2种格式如何转换在后面会说明。
以下如无特指均指JDOM里的Document。
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);
(2)从文件、流、系统ID、URL得到Document对象:
使用dom
DOMBuilder builder = new DOMBuilder(); Document doc = builder.build(new File("jdom_test.xml"));
SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(url);
这里举一个小例子,为了简单起见,使用String对象直接作为xml数据源:
public class App { public static void main(String[] args) throws Exception { StringBuilder textXml = new StringBuilder("<companies><name>baidu</name>"); textXml.append("<contry>CN</contry><ceo>liyanhong</ceo></companies>"); // 使用SAXBuilder SAXBuilder builder = new SAXBuilder(); Document doc = null; Reader in = new StringReader(textXml.toString()); doc = builder.build(in); Element root = doc.getRootElement(); //将子元素放入列表 List<Element> ls=root.getChildren(); //迭代输出子元素的文本内容 Iterator<Element> iter = ls.iterator(); while(iter.hasNext()){ System.out.println(iter.next().getText()); } } }输出:
baidu
CN
liyanhong
(3)DOM的document和JDOM的Document之间的相互转换使用方法
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);
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);
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");//获得指定名称的第一个子元素
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:
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); // 出错!补充:纠错性
(3)Element的文本内容读取
String desc = element.getText(); //清除前后空格 String desc = element.getTextTrim();
3.可正确解释特殊字符
?
4.CDATA的数据写入、读出
element.addContent(new CDATA(" content"));
String noDifference = element.getText();
混合内容
element可能包含很多种内容,比如说Some text,Some child element
取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类
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)操作
?
6.命名空间操作
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); } }
public class CreateXML { @Test public void create() 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("1001"); name.setText("chenjazz"); 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")); } }
在项目根目录生成的文件为:
<?xml version="1.0" encoding="gb2312"?> <student-info> <student> <number>1001</number> <name>chenjazz</name> <age>24</age> </student> </student-info>
public class CreateXML { @Test public void create() throws Exception { Document doc = new Document(); Map<Object, Object> map =new HashMap<Object, Object>(); map.put("xxxx", "1111"); ProcessingInstruction pi = new ProcessingInstruction("xml-stylesheet",map); 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); XMLOutputter outputter = new XMLOutputter(); outputter.output(doc, new FileWriter("test.xml")); } }
2、读取xml文档的例子:
package com.jazz.testm.testm_t1; import java.util.List; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import org.junit.Test; public class CreateXML { @Test public void parse() throws Exception { SAXBuilder builder = new SAXBuilder(); Document read_doc = builder.build("studentinfo.xml"); Element stu = read_doc.getRootElement(); List<Element> list = stu.getChildren("student"); for (int i = 0; i < list.size(); i++) { Element e = 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验证的:
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); } } }
5、Xpath例子:
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类 型)。
6、数据输入
要用到XML文档要通过org.jdom.input包,反过来需要org.jdom.output。
我们的例子读入XML文件exampleA.xml,加入一条处理指令,修改第一本书的价格和作者,并添加一条属性,然后写入文件exampleB.xml:
package com.jazz.testm.testm_t1; import java.io.FileInputStream; import java.io.FileOutputStream; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.ProcessingInstruction; import org.jdom.input.SAXBuilder; import org.jdom.output.XMLOutputter; import org.junit.Test; public class CreateXML { @Test public void parse() 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)); XMLOutputter outp = new XMLOutputter(); outp.output(doc, new FileOutputStream("exampleB.xml")); } }