java dom4j 解析XML文件 简易教程
2015-08-08 09:25
721 查看
XML
来自:W3School
XML 被设计用来传输和存储数据。
HTML 被设计用来显示数据。
什么是 XML?
eXtensible Markup LanguageXML 指可扩展标记语言(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 中编写注释的语法与 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种解析方式
来自http://bbs.csdn.net/topics/290027113/
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文件
从零开始制作XMLpublic 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>
相关文章推荐
- java集合(工具类Arrays)
- Java中的正则表达式
- SpringMVC接收请求参数和页面传递参数
- Java线程的暂停与继续
- java集合(工具类Collections)
- springmvc与mybatis的整合项目
- java 中 BigDecimal 怎么与 0 比较
- java中的get,set
- 简单说说java的事件模型
- Android eclipse导入项目后出现Unable to resolve target 'android-17'解决方法
- Font '??' is not available to the JVM. See the Javadoc for more details.
- eclipse中常用的快捷键
- springmvc 注解的适配器和映射器的配置
- hibernate Java 时间和日期类型 Hibernate 制图
- springmvc 前端控制器,映射器,适配器,视图解析器
- java中的debug使用
- eclipse无法连接genymotion+Unable to start the Genymotion virtual device
- eclipse无法连接genymotion+Unable to start the Genymotion virtual device
- springmvc的执行流程详解
- eclipse插件地址收集