java jdom 路径_JDOM 操作XML

可扩展标记语言——eXtensible Markup Language

用户可以自己定义语言标记,只要有开始和闭合标签即可。

xsl装饰、修饰xml的显示结果。

dtd约束xml文件中的标记。

Ø XML的优点:

1、xml可以让数据和标记分离。

2、异质信息互通

3、机器语言

4、用交流语言替代html装饰语言

5、简单易用

6、可以自定义、可扩展

Ø XML和HTML比较比较内容 HTML XML

可扩展性 不具有扩展性、标记固定 是元标记语言,可以定义新标记,用户可以自定义标记

侧重点 侧重于信息的表现形式为什么格式被关注 侧重于结构化的描述信息,数据是什么为XML所关注

语法 不严格(嵌套、配对) 严格嵌套、配对,并按照DTD要求输出

可读性、可维护性 难于阅读和维护 结构清晰,便于阅读维护

数据本身、显示 数据和显示合为一处 数据与显示分离

重用性 低 可重用性高

Ø JDOM操作XML

JDOM可以很方便的操作XML文档,完成XML内容的创建、修改,已经遍历Document文档中的XML元素,完成查询等。下面我们就用JDOM完成这些功能。

# 准备

首先我们要准备jdom相关的jar包

jaxen在jdom的zip压缩包中可以找到。

Junit是测试用的,可以不添加。但需要用main方法测试。

其次,是准备测试工作。部分测试代码:

package com.hoo.test;import java.io.File;import java.io.IOException;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import org.jdom.Attribute;import org.jdom.Comment;import org.jdom.Document;import org.jdom.Element;import org.jdom.JDOMException;import org.jdom.Namespace;import org.jdom.Text;import org.jdom.input.SAXBuilder;import org.jdom.output.XMLOutputter;import org.jdom.xpath.XPath;import org.junit.After;import org.junit.Before;import org.junit.Test;/*** function: JDOM操作XML* @author hoojo* @createDate 2011-8-4 下午12:34:09* @file DocumentTest.java* @package com.hoo.test* @project JDOMTest* @blog http://blog.csdn.net/IBM_hoojo* @email hoojo_@126.com* @version 1.0*/public class DocumentTest {private XMLOutputter out = null;@Beforepublic void init() {//输出文件信息out = new XMLOutputter();}@Afterpublic void destory() {if (out != null) {out = null;}System.gc();}/*** function:输出Document文档信息* @author hoojo* @createDate 2011-8-5 下午12:10:27* @param doc*/private void print(Document doc) {//设置XML文件编码格式//out.setFormat(Format.getCompactFormat().setEncoding("gb2132"));System.out.println(out.outputString(doc));}private void fail(Object o) {if (o != null) {System.out.println(o);}}}

# 创建Document

/*** 创建xml元素*/@Testpublic void createDoc() {Document doc = null;//method 1、创建一个Doc文档,添加一个元素rootdoc = new Document(new Element("root"));print(doc);//method 2、创建一个Doc文档,添加一个元素root,设置root元素的节点文本doc = new Document(new Element("root").setText("this is a root el"));print(doc);//method 3、创建一个Doc文档,添加一个元素root,设置root元素的节点文本且添加一个属性id,值为110Element root = new Element("root");root.setText("this is a root el");root.setAttribute("id", "110");doc.setRootElement(root);fail("method 3: \n" + out.outputString(doc));//method 4、创建一个Doc文档,添加一个元素root,设置root元素的节点文本doc = new Document();doc.addContent(new Element("root").setText("this is a root el"));fail("method 4: \n" + out.outputString(doc));fail(doc.toString());}

* new Document可以创建一个doc文档

当给Document传递一个Element参数时,这个Element就是根元素;

当调用Document的setRootElement方法时,可以设置当前Doc的根元素;

当调用doc的addContent的时候,添加的元素将会是根元素;

doc = new Document(new Element("root").setText("this is a root el"));

上面就创建了一个doc,根元素是root,root节点的内容是this is a root el;

注意setText方法返回的对象是当前Element,类似是StringBuffer的append方法;

* new Element()可以创建一个元素

如果传递参数那么这个参数将会是元素节点的名称;

Element的setText方法可以设置元素的文本值;

Element root = new Element("root");

root.setText("this is a root el");

创建一个节点名称为root的元素,文本是this is a root el

* setAttribute()可以设置某个具体节点的属性值

root.setAttribute("id", "110");

给root节点添加一个id,值为110

* addContent添加注释

root .addContent(new Comment("注释"));

在root元素下添加一个注释;

addContent是向元素中添加内容,而setContent是设置内容;

* setText设置元素文本内容

root.setText("this is a root el");

同样

root. setContent(new Text("this is text"))

同样

root.addContent("this is text");

下面用上面的这些方法,创建一篇XML文档。文档内容如下:

/**创建一遍xml文档<?xml version="1.0" encoding="UTF-8"?>ToyotaCelica1997green1ABC234*/@Testpublic void createXMLDoc() {//创建一个car的元素Element carEl = new Element("car");//创建vin属性,并设置值carEl.setAttribute("vin", "123fhg5869705iop90");//创建注释carEl.addContent(new Comment("Description of a car"));//创建一个make元素,设置文本内容carEl.addContent(new Element("make").setText("Toyota"));//创建一个model元素,添加一个文本元素carEl.addContent(new Element("model").setContent(new Text("Celica")));//创建一个year元素,添加文本内容carEl.addContent(new Element("year").addContent("1997"));//创建一个color元素,文本内容是greencarEl.addContent(new Element("color").setText("green"));//创建一个license的元素Element licenseEl = new Element("license");//为license元素添加文本内容licenseEl.addContent("1ABC234");//创建一个state的属性,值为CAlicenseEl.setAttribute("state", "CA");//将licenseEl添加到根元素中carEl.addContent(licenseEl);//将car元素设置为根元素Document doc = new Document(carEl);print(doc);/*out = new XMLOutputter();try {out.output(doc, System.out);} catch (IOException e) {e.printStackTrace();}*/}

方法运行后,所创建的文档和上面注释文档内容相同

# 读取XML文件的内容

disk.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>8G200158010G500300011G50Java bookSpring.txtstrtus.doc500

读取disk文件的内容,代码如下:

/*** function:读取xml文件中的元素* @author hoojo* @createDate 2011-8-4 下午04:54:17*/@Test@SuppressWarnings("unchecked")public void readXMLContent() {SAXBuilder builder = new SAXBuilder();try {Document doc = builder.build(new File("file/disk.xml"));Element rootEl = doc.getRootElement();//获得所有子元素List list = rootEl.getChildren();//List list = rootEl.getChildren("disk");for (Element el : list) {//获取name属性值String name = el.getAttributeValue("name");//获取子元素capacity文本值String capacity = el.getChildText("capacity");//获取子元素directories文本值String directories = el.getChildText("directories");String files = el.getChildText("files");System.out.println("磁盘信息:");System.out.println("分区盘符:" + name);System.out.println("分区容量:" + capacity);System.out.println("目录数:" + directories);System.out.println("文件数:" + files);System.out.println("-----------------------------------");}} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

* getChildren方法可以获取所有子元素

* getChildren(elName)可以获取所有名称为elName的子节点

* getAttributeValue可以获取指定属性的值

* getChildText可以获取子节点的文本值

# 递归显示文档信息

/*** 递归返回指定格式的“--”*/private String format(int i) {String temp = "";if (i > 0) {temp += "--";i--;temp += format(i);}return temp;}/*** function:显示当前节点所有Element的属性信息* @author hoojo* @createDate 2011-8-4 下午06:10:53* @param el* @return*/@SuppressWarnings("unchecked")private String getAttrInfo(Element el) {List attrs = el.getAttributes();return getAttrInfo(attrs);}/*** function:显示属性信息* @author hoojo* @createDate 2011-8-9 下午03:52:59* @param attrs* @return*/private String getAttrInfo(List attrs) {StringBuilder info = new StringBuilder();for (Attribute attr : attrs) {info.append(attr.getName()).append("=").append(attr.getValue()).append(", ");}if (info.length() > 0) {return "[" + info.substring(0, info.length() - 2)+ "]";}return "";}/*** function:递归显示文档节点元素信息* @author hoojo* @createDate 2011-8-4 下午05:56:34* @param i* @param list*/@SuppressWarnings("unchecked")private void print(int i, List list) {i++;for (Element el : list) {List childs = el.getChildren();if (childs.size() > 0) {fail(format(i) + el.getName() + " " + getAttrInfo(el));print(i, childs);} else {fail(format(i) + el.getName() + ":" + el.getText() + " " + getAttrInfo(el));}}}

调用print(0, root.getChildren());方法就可以看到一篇格式化后输出的文档内容

#############显示文档信息###############

--HD

----disk [name=C]

------capacity:8G

------directories:200

------files:1580

----disk [name=D]

------capacity:10G

------directories:500

------files:3000

----disk2 [name=E]

------capacity:11G

------directories:50

------files [size=200, modifyDate=2011-08-3]

--------file:Java book

--------file:Spring.txt

--------file:strtus.doc

----files:500 [size=220]

# XPath查询遍历XML文档

/*** function:用xpath遍历xml信息* @author hoojo* @createDate 2011-8-4 下午04:56:52* xpath参考:http://www.w3school.com.cn/xpath/xpath_functions.asp** nodeName 选取此节点的所有子节点/ 从根节点选取// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的. 选取当前节点.. 选取当前节点的父节点@ 选取属性* 匹配任何元素节点@* 匹配任何属性节点node() 配任何类型的节点ancestor 选取当前节点的所有先辈(父、祖父等)ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身attribute 选取当前节点的所有属性child 选取当前节点的所有子元素。descendant 选取当前节点的所有后代元素(子、孙等)。descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。following 选取文档中当前节点的结束标签之后的所有节点。namespace 选取当前节点的所有命名空间节点parent 选取当前节点的父节点。preceding 选取文档中当前节点的开始标签之前的所有节点。preceding-sibling 选取当前节点之前的所有同级节点。self 选取当前节点。child::book 选取所有属于当前节点的子元素的 book 节点attribute::languane 选取当前节点的 languange 属性child::* 选取当前节点的所有子元素attribute::* 选取当前节点的所有属性child::text() 选取当前节点的所有文本子节点child::node() 选取当前节点的所有子节点descendant::book 选取当前节点的所有 book 后代ancestor::book 选择当前节点的所有 book 先辈*/@SuppressWarnings("unchecked")@Testpublic void queryElementByXPath() {SAXBuilder builder = new SAXBuilder();try {Document doc = builder.build(new File("file/disk.xml"));List list = XPath.selectNodes(doc, "/HD/disk");for (Element el : list) {String name = el.getAttributeValue("name");String capacity = el.getChildText("capacity");String directories = el.getChildText("directories");String files = el.getChildText("files");System.out.println("磁盘信息:");System.out.println("分区盘符:" + name);System.out.println("分区容量:" + capacity);System.out.println("目录数:" + directories);System.out.print("文件数:" + files);String capacityText = ((Text) XPath.selectSingleNode(el, "//disk[@name='" + name + "']/capacity/text()")).getTextNormalize();System.out.println("#" + capacityText);System.out.println("-----------------------------------");}//显示文档信息System.out.println("#############显示文档信息###############");print(0, doc.getContent());//获得hd元素System.out.println("#############显示HD子元素信息###############");Element root = (Element) XPath.selectSingleNode(doc, "/HD");//fail(root.getChildren().size());print(0, root.getChildren());//获取hd下所有元素System.out.println("#############显示HD子元素信息###############");List roots = (List) XPath.selectNodes(doc, "/HD/*");//fail(roots.size());print(0, roots);//获得hd下的所有disk元素System.out.println("#############显示disk信息###############");roots = (List) XPath.selectNodes(doc, "/HD/disk");//fail(roots.size());print(0, roots);System.out.println("#############显示disk2信息###############");roots = (List) XPath.selectNodes(doc, "/HD/disk2");print(0, roots);System.out.println("#############显示任意路径下的files信息###############");roots = (List) XPath.selectNodes(doc, "//files");print(0, roots);System.out.println("#############显示任意路径下的files指定下标的file信息###############");roots = (List) XPath.selectNodes(doc, "//files/file[1]");print(0, roots);System.out.println("#############显示任意路径下的files最后的file信息###############");roots = (List) XPath.selectNodes(doc, "//files/file[last()]");print(0, roots);System.out.println("#############显示任意路径下的files倒数第二的file信息###############");roots = (List) XPath.selectNodes(doc, "//files/file[last() - 1]");print(0, roots);System.out.println("#############显示任意路径下的files的子元素file位置position在第二的file信息###############");roots = (List) XPath.selectNodes(doc, "//files/file[position() = 2]");//roots = (List) XPath.selectNodes(doc, "//files/file[position() > 2]");print(0, roots);System.out.println("#############显示任意路径下的files第三个file的当前节点的前面所有同级节点信息###############");roots = (List) XPath.selectNodes(doc, "//files/file[3]/preceding-sibling::*");print(0, roots);System.out.println("#############显示任意路径下的disk2之前的所有节点信息###############");roots = (List) XPath.selectNodes(doc, "//disk2/preceding::*");print(0, roots);System.out.println("#############显示任意路径下的disk2之后的所有节点信息###############");roots = (List) XPath.selectNodes(doc, "//disk2/following::*");print(0, roots);System.out.println("#############显示任意路径下的files的所有属性信息###############");roots = (List) XPath.selectNodes(doc, "//files/attribute::*");fail(getAttrInfo(roots));System.out.println("#############显示任意路径下的节点是disk属性name=C的信息###############");roots = (List) XPath.selectNodes(doc, "//disk[@name='C']");print(0, roots);System.out.println("#############显示任意路径下的节点是disk的子元素的文本中含义5和8节点的信息###############");roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') and contains(text(), '5')]");//roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') or contains(text(), '5')]");print(0, roots);System.out.println("#############显示任意路径下的节点是files且有属性size的信息###############");roots = (List) XPath.selectNodes(doc, "//files[@size]");print(0, roots);System.out.println("#############显示HD节点下capacity的值为11G的信息###############");//roots = (List) XPath.selectNodes(doc, "/HD/disk/capacity[text()='11G']");roots = (List) XPath.selectNodes(doc, "/HD/*/capacity[text()='11G']");//roots = (List) XPath.selectNodes(doc, "/*/*/capacity[text()='11G']");print(0, roots);//parent::*表示父节点集合System.out.println("#############显示任意路径下的节点是files且属性size有值的父节点的信息###############");roots = (List) XPath.selectNodes(doc, "//files[@size='200']/parent::*");print(0, roots);System.out.println("#############显示任意路径下的节点disk的子节点的capacity信息###############");roots = (List) XPath.selectNodes(doc, "//disk/child::capacity");print(0, roots);//获取c盘的大小System.out.println("获取c盘的大小");Text filesText = (Text) XPath.selectSingleNode(doc, "/HD/disk[@name='C']/files/text()");System.out.println(filesText.getTextNormalize());//XPath function/**string concat (string, string, string*) 联接两个字符串boolean starts-with (string, string) 判断某字符串是否以另一字符串开头boolean contains (string, string) 判断某字符串是否包含另一字符串string substring (string, number, number) 取子字符串number string-length (string) 测字符串长度number sum (node-set) 求和number floor (number) 求小于此数的最大整数值number ceiling (number) 求大于此数最小整数值**/System.out.println("获取@size的和大于200的");roots = (List) XPath.selectNodes(doc, "//files[sum(@size) > 200]");print(0, roots);System.out.println("查找directories的内容长度小于3的");roots = (List) XPath.selectNodes(doc, "//directories[string-length(text()) < 3]");print(0, roots);System.out.println("查找files的内容包含5的");roots = (List) XPath.selectNodes(doc, "//files[contains(text(), '5')]");print(0, roots);} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

# 删除元素及其他操作

/*** function:打印doc相关信息* @author hoojo* @createDate 2011-8-10 下午06:29:01*/@SuppressWarnings("unchecked")@Testpublic void printInfo() {SAXBuilder builder = new SAXBuilder();try {//builder.setFeature("user", true);//builder.setIgnoringBoundaryWhitespace(true);//忽略元素内容的空格//builder.setIgnoringElementContentWhitespace(true);Document doc = builder.build(new File("file/web.xml"));fail("baseURI: " + doc.getBaseURI());fail("ContentSize: " + doc.getContentSize());//System.out.println("getContent: ");//print(0, doc.getContent());fail("getContent index: " + doc.getRootElement().getContent(1));fail("getDocType: " + doc.getDocType());fail("getParent: " + doc.getRootElement().getContent(1).getParent());fail("getProperty: " + doc.getProperty("filter"));print(0, XPath.selectNodes(doc, "//*[contains(text(), '#')]"));fail("getText: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getText());fail("getTextTrim: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getTextTrim());fail("getTextNormalize: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getTextNormalize());fail("hasRootElement: " + doc.hasRootElement());//如果文档带有Namespace一定要设置Namespace,不然无法读取内容Namespace ns = Namespace.getNamespace("http://java.sun.com/xml/ns/javaee");Element servletEl = doc.getRootElement().getChild("servlet", ns);fail("servletEl: " + servletEl);print(0, servletEl.getChildren());fail("getChildText: " + servletEl.getChildText("servlet-class", ns));fail("getChildTextNormalize: " + servletEl.getChildTextNormalize("servlet-name", ns));fail("getChildTextTrim: " + servletEl.getChildTextTrim("servlet-class", ns));fail("getName: " + servletEl.getName());fail("getNamespacePrefix: " + servletEl.getNamespacePrefix());fail("getNamespace: " + servletEl.getNamespace());fail("getQualifiedName: " + servletEl.getQualifiedName());Element classEl = servletEl.getChild("servlet-class", ns);fail("getText: " + classEl.getText());fail("getTextNormalize: " + classEl.getTextNormalize());fail("getTextTrim: " + classEl.getTextTrim());fail("getValue: " + classEl.getValue());//删除节点fail(doc.getRootElement().removeContent(3));//print(0, doc.removeContent());//print(0, doc.getRootElement().getChildren());fail(servletEl.removeChild("servlet-class", ns));fail(servletEl.removeChildren("init-param", ns));print(0, servletEl.getChildren());} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

作者:hoojo

出处:

blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权所有,转载请注明出处 本文出自:

lg-share-cn.gif版权所有,欢迎转载,转载请注明出处,谢谢

posted on 2011-08-10 18:40 hoojo 阅读(2120) 评论(0)  编辑  收藏 所属分类: JavaEE 、JavaSE 、JSON&XML

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值