码迷,mamicode.com
首页 > 编程语言 > 详细

java dom4j 解析XML文件 简易教程

时间:2015-08-08 10:34:19      阅读:369      评论:0      收藏:0      [点我收藏+]

标签:java   xml   dom4j   

XML

来自:
W3School

XML 被设计用来传输和存储数据。
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 的属性值须加引号
  • 实体引用
实体 引用 意义
&lt; < 小于
&gt; > 大于
&amp; & 和号
&apos; 单引号
&quot; " 引号

- 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文件

从零开始制作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();
    }

相关类和接口

技术分享

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 dom4j 解析XML文件 简易教程

标签:java   xml   dom4j   

原文地址:http://blog.csdn.net/havedream_one/article/details/47355223

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!