使用dom4j需要导入jar包
jar包下载地址:http://pan.baidu.com/s/1o65jWRw
将dom4j-1.6.1.jar包导入Eclipse
book2.xml
解析book2.xml这个文件。
方法:
获取文档的根结点:
Element root = document.getRootElement();
获取某个结点的子节点
Element element = root.element();
获取某个结点下的所有子节点:
List elements = root.elements();
遍历该结点下的所有子节点
以递归的方式进行
ML
来自:
W3SchoolXML 被设计用来传输和存储数据。HTML 被设计用来显示数据。
什么是 XML?
eXtensible Markup Language
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准
XML 与 HTML 的主要差异
- XML 不是 HTML 的替代。
- XML 和 HTML 为不同的目的而设计:
- XML 被设计为传输和存储数据,其焦点是数据的内容。
- HTML 被设计用来显示数据,其焦点是数据的外观。
- HTML 旨在显示信息,而 XML 旨在传输信息。
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
- XML 不是对 HTML 的替代
- XML 是对 HTML 的补充。
- XML 不会替代 HTML,理解这一点很重要。在大多数 web 应用程序中,XML 用于传输数据,而 HTML 用于格式化并显示数据。
对 XML 最好的描述是:XML 是独立于软件和硬件的信息传输工具。
XML 的用途
XML 应用于 web 开发的许多方面,常用于简化数据的存储和共享。
XML 把数据从 HTML 分离。如果你需要在 HTML 文档中显示动态数据,那么每当数据改变时将花费大量的时间来编辑 HTML。通过 XML,数据能够存储在独立的 XML 文件中。这样你就可以专注于使用 HTML 进行布局和显示,并确保修改底层数据不再需要对 HTML 进行任何的改变。
XML树结构
XML 文档形成了一种树结构,它从“根部”开始,然后扩展到“枝叶”。
XML 文档必须包含根元素。该元素是所有其他元素的父元素。
XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。所有元素均可拥有子元素:
<root>
<child>
<subchild>.....</subchild>
</child>
</root>
父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。相同层级上的子元素成为同胞(兄弟或姐妹)。
所有元素均可拥有文本内容和属性(类似 HTML 中)。
如:
根元素是 <bookstore>。文档中的所有 <book> 元素都被包含在 <bookstore> 中。<book> 元素有 4 个子元素:<title>、< author>、<year>、<price>。
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
XML 语法规则
- 所有 XML 元素都须有关闭标签
- XML 标签对大小写敏感
- XML 必须正确地嵌套
- XML 文档必须有根元素
- XML 的属性值须加引号
- 实体引用
实体 | 引用 | 意义 |
---|---|---|
< | < | 小于 |
> | > | 大于 |
& | & | 和号 |
' | ' | 单引号 |
" | " | 引号 |
- XML 中的注释
在 XML 中编写注释的语法与 HTML 的语法很相似:
<!- - This is a comment - ->
- 在 XML 中,空格会被保留
- XML 以 LF 存储换行
XPATH
XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言
最有用的路径表达式:
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
路径表达式 | 结果 |
---|---|
bookstore | 选取 bookstore 元素的所有子节点。 |
/bookstore | 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取名为 lang 的所有属性。 |
Java解析XML文件
4种解析方式
DOM(Document Object Model JAXP Crimson解析器)
DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。DOM以及广义的基于树的处理具有几个优点。首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像SAX那样是一次性的处理。DOM使用起来也要简单得多。
SAX(Simple API for XML)
SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX还比它的替代者DOM快许多。
DOM解析器把XML文档转化为一个包含其内容的树,并可以对树进行遍历。用DOM解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用DOM解析器的时候需要处理整个XML文档,所以对性能和内存的要求比较高,尤其是遇到很大的XML文件的时候。由于它的遍历能力,DOM解析器常用于XML文档需要频繁的改变的服务中。
SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体现。但用SAX解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。
JDOM http://www.jdom.org
JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于是第一个Java特定模型,JDOM一直得到大力推广和促进。正在考虑通过“Java规范请求JSR-102”将它最终用作“Java标准扩展”。从2000年初就已经开始了JDOM开发。
JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。
DOM4J http://dom4j.sourceforge.net
虽然DOM4J代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过DOM4J API和标准DOM接口具有并行访问功能。
比较
1)DOM4J性能最好,连Sun的JAXM也在用DOM4J.目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.
2)JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM.虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。
3)SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。
dom4j简易教程
获取Document
SAXReader reader = new SAXReader();
Document document = reader.read("bookstore.xml");
Iterator
public void bar(Document document) throws DocumentException
Element root = document.getRootElement();
// iterate through child elements of root
for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
Element element = (Element) i.next();
// do something
}
// iterate through child elements of root with element name "foo"
for ( Iterator i = root.elementIterator( "foo" ); i.hasNext(); ) {
Element foo = (Element) i.next();
// do something
}
// iterate through attributes of root
for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
Attribute attribute = (Attribute) i.next();
// do something
}
}
XPath表达式
public static void main(String[] args) throws DocumentException
{
System.out.println("Hello World!");
SAXReader sax = new SAXReader();
Document document = sax.read("bookstore.xml");
List<Node> list = document.selectNodes( "//book/title" );
for(Node n : list){
System.out.println("=======================");
System.out.println("节点名:" + n.getName());
System.out.println("节点值:" + n.getText());
System.out.println("节点XPath:" + n.getPath());
System.out.println("节点属性lang值:" + n.valueOf("@lang"));
System.out.println("节点所属的xml文档对象:" +n.getDocument().equals(document));
System.out.println("节点父亲名字:" + n.getParent().getQName().getName());
System.out.println("节点类型:" + n.getNodeTypeName());
}
Node node = document.selectSingleNode( "/bookstore/book" );
String name = node.valueOf( "@category" );
System.out.println(name);
System.out.println(node.getDocument());
}
快速遍历
public static void main(String[] args) throws DocumentException
{
System.out.println("Hello World!");
SAXReader sax = new SAXReader();
Document document = sax.read("bookstore.xml");
Element root = document.getRootElement();
DFS(root);
}
public static void DFS(Element e){
System.out.println(e.getQName().getName()+"------------"+e.getNodeTypeName());
for ( int i = 0, size = e.nodeCount(); i < size; i++ ) {
Node node = e.node(i);
if ( node instanceof Element ) {
DFS( (Element) node );
}
else {
if(node.getText().trim().length() > 0){
System.out.println(node.getNodeTypeName()+"-------------" + node.getText().trim());
}
}
}
}
制作新XML文件
从零开始制作XML
public static void main(String[] args) throws Exception
{
System.out.println("Hello World!");
//1. 创建Document对象
Document document = createDocument();
//2. 将Document写入文件,两种方式,简洁方式和美观方式
//2.1 简洁方式,设置OutputFormat为compact
//2.2 美观方式,设置OutputFormat为pretty
write(document);
}
public static Document createDocument(){
Document document = DocumentHelper.createDocument();
Element root = document.addElement("root");
Element author1 = root.addElement( "author" )
.addAttribute( "name", "James" )
.addAttribute( "location", "UK" )
.addText( "James Strachan" );
Element author2 = root.addElement( "author" )
.addAttribute( "name", "Bob" )
.addAttribute( "location", "US" )
.addText( "Bob McWhirter" );
return document;
}
public static void write(Document document) throws Exception {
// lets write to a file
XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ) );
writer.write( document );
writer.close();
// Pretty print the document to System.out
OutputFormat format = OutputFormat.createPrettyPrint();
writer = new XMLWriter( System.out, format );
writer.write( document );
writer.close();
// Compact format to System.out
format = OutputFormat.createCompactFormat();
writer = new XMLWriter( System.out, format );
writer.write( document );
writer.close();
}
字符串与XML互换
实现字符串和XML文件之间的转换
public static void main(String[] args) throws Exception
{
System.out.println("Hello World!");
SAXReader sax = new SAXReader();
Document document = sax.read("bookstore.xml");
//将XML文件转成string
String str = document.asXML();
System.out.println(str);
//删除换行
str = str.replaceAll("[\n]","");
System.out.println(str);
//将string转换成document对象,然后写入XML文件
Document document1 = DocumentHelper.parseText(str);
XMLWriter writer = new XMLWriter(new FileWriter("stringToXML.xml"));
writer.write(document1);
writer.flush();
writer.close();
}
实例
将一个XML文件转换成类对象1、创建xml文件
<?xml version="1.0" ?>
<root>
<Book>
<category>COOKING</category>
<title>Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</Book>
<Book>
<category>CHILDREN</category>
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</Book>
<Book>
<category>WEB</category>
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</Book>
</root>
2、编写java bean文件3、转换类
public class XMLToClass
{
public static void main(String[] args)
{
System.out.println("Hello World!");
readXML("classXML.xml");
}
public static void readXML(String xmlFileName) {
SAXReader sax = new SAXReader();
Document document = null;
try{
document = sax.read(xmlFileName);
}catch(DocumentException dex){
dex.printStackTrace();
System.out.println("获取Document对象失败");
return;
}
Element root = document.getRootElement();
List<Element> objs = root.elements();
List<Element> properties = null;
String className = "";
if(objs.size() > 0){
//获取类名
className = objs.get(0).getQName().getName();
properties = objs.get(0).elements();
}
System.out.println("类名:" + className);
List<String> pros = new ArrayList<String>();
for(int i = 0 ; i < properties.size(); i ++){
System.out.println("属性"+i+":"+properties.get(i).getQName().getName());
pros.add(properties.get(i).getQName().getName());
}
System.out.println(pros);
List<Object> list = createObject(className,objs);
for(Object o : list){
System.out.println(o);
}
}
/*
* 根据类名,属性值构造对象
*/
public static List<Object> createObject(String className,List<Element> objNodes){
Class clazz = null;
try{
clazz = Class.forName(className);
}catch(ClassNotFoundException cnfe){
System.out.println(className + "没有找到!");
}
List<Object> objs = new ArrayList<Object>();
for(int i = 0; i < objNodes.size(); i++){
List<Element> properties = objNodes.get(i).elements();
try{
Object obj = clazz.newInstance();
for(int j = 0; j < properties.size(); j ++){
Element e = properties.get(j);
Field field = clazz.getDeclaredField(e.getQName().getName());
field.setAccessible(true);
//获取域的类型,需要选择field的set方法
String type = field.getType().getName();
if("int".equals(type)){
field.setInt(obj,Integer.parseInt(e.getText().trim()));
}else if("double".equals(type)){
field.setDouble(obj,Double.parseDouble(e.getText().trim()));
}else{
field.set(obj,e.getText().trim());
}
}
objs.add(obj);
}catch(InstantiationException ie){
System.out.println("实例化类失败!");
}catch(NoSuchFieldException nse){
System.out.println("找不到指定的数据域!");
}catch(IllegalAccessException iae){
System.out.println("底层字段是不可访问的!");
}
}
return objs;
}
}
相关类和接口
Document
实现了Node接口
获取根元素Element getRootElement()
Element
方法 | 意义 |
---|---|
Iterator elementIterator() | 返回一个包含子元素的迭代器 |
List elements() | 返回子元素列表 |
Element element(String name) | 根据name获取Element |
QName getQName() | 获取元素的QName名字 |
int attributeCount() | 获取属性个数 |
Attribute attribute(int index) | 第index个属性 |
getText() | 如果元素有值,则获取值 |
String elementText(String name) | 获取值 |
public static void main(String[] args) throws DocumentException
{
System.out.println("Hello World!");
SAXReader sax = new SAXReader();
Document document = sax.read("bookstore.xml");
//获取xml的根元素
Element root = document.getRootElement();
System.out.println(root.getQName().getName());
//获取指定的元素,根据QName或者name
Element foo = root.element("foo");
//获取元素的属性个数
System.out.println("属性个数:" + foo.attributeCount());
for(int i = 0; i < foo.attributeCount(); i++){
//获取元素的属性,三种方式QName,Name,Index
Attribute a = foo.attribute(i);
//获取属性值
System.out.println(a.getQName().getName() + "=" + a.getValue());
}
//获取属性列表
List<Attribute> list = foo.attributes();
for(Attribute a : list){
System.out.println(a.getQName().getName() + "=" + a.getValue());
}
//获取指定属性名的值
System.out.println("color:"+foo.attributeValue("color"));
System.out.println("================================");
List<Element> list1 = root.elements("book");
System.out.println();
for(Element e : list1){
Element child = e.element("title");
System.out.println(child.getText());
System.out.println(e.elementText("title"));
}
}
Attribute
方法 | 意义 |
---|---|
QName getQName() | 返回属性名QName() |
String getValue() | 获取属性值 |
void setValue(String value) | 设置属性值,若是只读则抛出异常UnsupportedOperationException |
QName
Namespace getNamespace()String getName()
SAXReader
读取xml文件read
Node
接口类型
最好熟悉XPath语法
方法 | 意义 |
---|---|
Document getDocument() | |
String getName() | 返回Node名 |
String getText() | 返回节点的文本内容,最好再使用string的trim()方法删除两端的换行符 |
Element getParent() | 返回父节点 |
short getNodeType() | 返回节点类型整数值 |
String getNodeTypeName() | 返回节点类型 |
List selectNodes(String xpathExpression) | 返回Node列表 |
write(Writer writer) |
Branch
接口类型
定义了节点的共同行为
方法 | 意义 |
---|---|
int indexOf(Node node) | |
Node node(int index) | |
int nodeCount() | |
Iterator nodeIterator() | |
void add(Comment comment) | Adds the given Comment to this branch. |
void add(Element element) | Adds the given Element to this branch. |
void add(Node node) | Adds the given Node or throws IllegalAddException if the given node is not of a valid type. |
Element addElement(String name) | Adds a new Element node with the given name to this branch and returns a reference to the new node. |
boolean remove(Comment comment) | Removes the given Comment if the node is an immediate child of this branch. |
boolean remove(Element element) | Removes the given Element if the node is an immediate child of this branch. |
boolean remove(Node node) | Removes the given Node if the node is an immediate child of this branch. |
XMLWriter
方法 | 意义 |
---|---|
XMLWriter() | 默认是简洁输出 |
XMLWriter(OutputFormat format) | |
XMLWriter(OutputStream out) | |
XMLWriter(OutputStream out, OutputFormat format) | |
XMLWriter(Writer writer) | |
XMLWriter(Writer writer, OutputFormat format) | |
void write(Document doc) | This will print the Document to the current Writer. |
OutputFormat
输出样式控制
方法 | 意义 |
---|---|
static OutputFormat createCompactFormat() | 简洁输出,没有添加为了美观的换行符,如: <root><author name="James" location="UK">James Strachan</author><author name="Bob" location="US">Bob McWhirter</author></root> |
static OutputFormat createPrettyPrint() | 美观输出,如下面所示 |
<root>
<author name="James" location="UK">James Strachan</author>
<author name="Bob" location="US">Bob McWhirter</author>
</root>