xml了解及读取和保存XML

xml学习体会

一、XML简介
HTML用于显示的。XML被设计的宗旨是描述数据的。

  • XML的标签是用户自行定义的。
  • XML是可扩展标记语言。

1、XML的作用
描述有关系和层次结构的数据

2、XML的应用
a、描述数据
b、作为配置文件

注:在Java开发中,传统的配置文件是properties文件。
扩展名必须是properties,文件中的内容是以key=value的形式存在的。

例:db.properties;user=root;password=root;#url=...               注释

二、XML的语法
1、XML文档声明
必须出现在第1行。
语法:<?xml version="1.0"?>   注意:?与xml之间不能有空格
   *version可以称为属性:取值固定1.0
   *encoding属性:说明xml文档采用的编码。默认为utf-8

   注意:保存到磁盘上使用的编码要与XML声明中的编码一致。否则出现错误
   standalone:说明该xml文档是否独立存在。

2、元素

  1. 必须有结束标签。
  2. 如果没有主题内容,标签<tag1></tag1>可以写为<tag1/>
  3. 必须合理嵌套
  4. 一个XML文档中,有且只有一个根元素
  5. XML不会忽略文档中出现的空格、回车换行、制表符。
  6. 命名规范:只能包含字母、数字、下划线、减号和英文句点。
  7. 严格区分大小写;
3、元素的属性
元素的属性名不能重复
属性的取值必须用引号引起来(单或双)
属性可以用子元素的形式来替代。

4、注释
语法:<!--这是注释-->
注意:
声明前不能有注释
注释必须合理嵌套

5、CDATA区
CDATA:Character Data字符数据
作用: 把元素等看做普通字符串
语法:<![CDATA[内容]]>

6、XML中的特殊字符
要在元素内容中显示特殊字符本身,需要使用替代符号
&    &amp;
<    &lt;
>    &gt;
"    &quot;
'     &apos;
7、处理指令:PI
作用:用来指挥软件如何解析XML文档。
语法:<?开头 ?>结尾
常用的指令:xml-stylesheet引入样式
例:<?xml-stylesheet type="text/css"?>

三、约束DTD
      1、 约束其实就是规定了XML中能出现的元素、属性个数及顺序等内容
      2、格式良好的XML文档:遵循XML语法的XML文档
      3、有效的XML文档:遵循约束的XML文档
      4、有效的XML文档必定是格式良好的,但格式良好的并不一定是有效的。

DTD:Document Type Definition文档类型定义
作用:约束XML编写

DTD文件保存到磁盘上时必须使用utf-8
 
1、编写DTD的方式
      a、直接在XML文档中编写(没有编码要求)
      语法:
            <!DOCTYPE 根元素名称[
                //DTD定义
            ]>
     b、在单独的文件中编写(文件的扩展名是dtd,且保存时必须使用utf-8编码)
       引入外部定义的DTD文档:
         1、 DTD文档在本地:
             <!DOCTYPE 根元素名称 SYSTEM "DTD文档的存放路径">
         2、 DTD文档在公共网络上:
            <!DOCTYPE 根元素名称 PUBLIC "DTD名称" "DTD的URL">
2、DTD语法细节(能看懂DTD)
     *a、定义元素
语法:<!ELEMENT 元素名称 使用规则>

     使用规则:
  1. (#PCDATA):Parsed Character Data 表明该元素的主体内容是普通字符串
  2. EMPTY:表明该元素是空元素
  3. ANY:用于指示元素的主体内容为任意类型。
  4. (子元素):指示该元素有哪些孩子,如果子元素用逗号分开,说明必须按照声明顺序去编写XML文档,如果子元素用“|”分开,说明任选其一
  5. 可以使用*、?、+说明元素出现的次数
*:0次或一次或多次
?:0次或一次
+:至少一次
什么都没有:有且必须一次

*b、定义属性
语法:
1、<!ATTLIST 元素名称
属性名1 属性值类型 设置说明 
属性名2 属性值类型 设置说明>
2、属性值类型:
CDATA:取值是普通字符数据
ENUMERATED (DTD没有此关键字):表示枚举,只能从枚举列表中任选其一,如(鸡肉|牛肉|猪肉|鱼肉)
ID:表示属性的取值不能重复
3、设置说明:
#REQUIRED:该属性是必须的
#IMPLIED:可选的属性
#FIXED:属性的取值为一个固定值。  #FIXED "固定值"
直接值:表示属性的取值为该默认值



c、定义实体(了解)
1、引用实体:
特点:在DTD中定义实体,在XML中使用
语法:<!ENTITY 实体名称 "内容">
在XML中如何引用实体:
&实体名称;
2、参数实体:
特点:在DTD中定义实体,在DTD中使用
语法:<!ENTITY % 实体名称 "内容">
在DTD中如何使用:
%实体名称;

 

xml 入门 dtd

xml dtd的格式:

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT classroom (className,grade,students)>
<!ATTLIST classroom id ID #REQUIRED>
<!ELEMENT className (#PCDATA)>
<!ELEMENT grade (#PCDATA)>
<!ELEMENT students (student+)>
<!ELEMENT student (id,name,age)>
<!ELEMENT id (#PCDATA)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>

相应的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE classroom SYSTEM "classroom.dtd">
<!--<!DOCTYPE classroom PUBLIC "http://www.zizhu.com/classroom">-->
<classroom id="p1">
    <className>2010计算机应用技术</className>
    <grade>2010</grade>
    <students>
        <student>
            <id>11</id>
            <name>zizhu8</name>
            <age>20</age>
        </student>
        <student>
             <id>12</id>
            <name>zizhu3</name>
            <age>20</age>
        </student>
    </students>
</classroom>

 

用 dom4j 解析 XML

dom4j API 包含一个解析 XML 文档的工具。本文中将使用这个解析器创建一个示例 XML 文档。清单 1 显示了这个示例 XML 文档,catalog.xml。


<?xml version="1.0" encoding="UTF-8"?> 
<catalog> 
<!--An XML Catalog--> 
<?target instruction?>
  <journal title="XML Zone" 
                  publisher="IBM developerWorks"> 
<article level="Intermediate" date="December-2001">
 <title>Java configuration with XML Schema</title> 
 <author> 
     <firstname>Marcello</firstname> 
     <lastname>Vitaletti</lastname> 
 </author>
  </article>
  </journal> 
</catalog>

然后使用同一个解析器修改 catalog.xml,清单 2 是修改后的 XML 文档,catalog-modified.xml。


<?xml version="1.0" encoding="UTF-8"?> 
<catalog> 
<!--An XML catalog--> 
<?target instruction?>
  <journal title="XML Zone"
                   publisher="IBM developerWorks"> 
<article level="Introductory" date="October-2002">
 <title>Create flexible and extensible XML schemas</title> 
 <author> 
     <firstname>Ayesha</firstname> 
     <lastname>Malik</lastname> 
 </author> 
  </article>
  </journal> 
</catalog>

与 W3C DOM API 相比,使用 dom4j 所包含的解析器的好处是 dom4j 拥有本地的 XPath 支持。DOM 解析器不支持使用 XPath 选择节点。

本文包括以下几个部分:

  • 预先设置
  • 创建文档
  • 修改文档

这个解析器可以从 http://dom4j.org 获取。通过设置使dom4j-1.4/dom4j-full.jar 能够在 classpath 中访问,该文件中包括 dom4j 类、XPath 引擎以及 SAX 和 DOM 接口。如果已经使用了 JAXP 解析器中包含的 SAX 和 DOM 接口,向 classpath 中增加dom4j-1.4/dom4j.jardom4j.jar 包括 dom4j 类和 XPath 引擎,但是不含 SAX 与 DOM 接口。


本节讨论使用 dom4j API 创建 XML 文档的过程,并创建示例 XML 文档 catalog.xml。

使用 import 语句导入 dom4j API 类:

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

使用 DocumentHelper 类创建一个文档实例。 DocumentHelper 是生成 XML 文档节点的 dom4j API 工厂类。

 Document document = DocumentHelper.createDocument();

使用 addElement() 方法创建根元素 catalogaddElement() 用于向 XML 文档中增加元素。

Element catalogElement = document.addElement("catalog");

catalog 元素中使用 addComment() 方法添加注释“An XML catalog”。

 catalogElement.addComment("An XML catalog");

catalog 元素中使用 addProcessingInstruction() 方法增加一个处理指令。

catalogElement.addProcessingInstruction("target","text");

catalog 元素中使用 addElement() 方法增加 journal 元素。

Element journalElement =  catalogElement.addElement("journal");

使用 addAttribute() 方法向 journal 元素添加 titlepublisher 属性。

journalElement.addAttribute("title", "XML Zone");
         journalElement.addAttribute("publisher", "IBM developerWorks");

article 元素中添加 journal 元素。

Element articleElement=journalElement.addElement("article");

article 元素增加 leveldate 属性。

articleElement.addAttribute("level", "Intermediate");
      articleElement.addAttribute("date", "December-2001");

article 元素中增加 title 元素。

Element titleElement=articleElement.addElement("title");

使用 setText() 方法设置 article 元素的文本。

titleElement.setText("Java configuration with XML Schema");

article 元素中增加 author 元素。

Element authorElement=articleElement.addElement("author");

author 元素中增加 firstname 元素并设置该元素的文本。

Element  firstNameElement=authorElement.addElement("firstname");
     firstNameElement.setText("Marcello");

author 元素中增加 lastname 元素并设置该元素的文本。

Element lastNameElement=authorElement.addElement("lastname");
     lastNameElement.setText("Vitaletti");

可以使用 addDocType() 方法添加文档类型说明。

document.addDocType("catalog", null,"file://c:/Dtds/catalog.dtd");

这样就向 XML 文档中增加文档类型说明:

<!DOCTYPE catalog SYSTEM "file://c:/Dtds/catalog.dtd">

如果文档要使用文档类型定义(DTD)文档验证则必须有 Doctype。

XML 声明 <?xml version="1.0" encoding="UTF-8"?> 自动添加到 XML 文档中。

清单 3 所示的例子程序 XmlDom4J.java 用于创建 XML 文档 catalog.xml。


import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;
import java.io.*;
public class XmlDom4J{
public void generateDocument(){
Document document = DocumentHelper.createDocument();
     Element catalogElement = document.addElement("catalog");
     catalogElement.addComment("An XML Catalog");
     catalogElement.addProcessingInstruction("target","text");
     Element journalElement =  catalogElement.addElement("journal");
     journalElement.addAttribute("title", "XML Zone");
     journalElement.addAttribute("publisher", "IBM developerWorks");
     Element articleElement=journalElement.addElement("article");
     articleElement.addAttribute("level", "Intermediate");
     articleElement.addAttribute("date", "December-2001");
     Element  titleElement=articleElement.addElement("title");
     titleElement.setText("Java configuration with XML Schema");
     Element authorElement=articleElement.addElement("author");
     Element  firstNameElement=authorElement.addElement("firstname");
     firstNameElement.setText("Marcello");
     Element lastNameElement=authorElement.addElement("lastname");
     lastNameElement.setText("Vitaletti");
     document.addDocType("catalog",
                           null,"file://c:/Dtds/catalog.dtd");
    try{
    XMLWriter output = new XMLWriter(
            new FileWriter( new File("c:/catalog/catalog.xml") ));
        output.write( document );
        output.close();
        }
     catch(IOException e){System.out.println(e.getMessage());}
}
public static void main(String[] argv){
XmlDom4J dom4j=new XmlDom4J();
dom4j.generateDocument();
}}

这一节讨论了创建 XML 文档的过程,下一节将介绍使用 dom4j API 修改这里创建的 XML 文档。


这一节说明如何使用 dom4j API 修改示例 XML 文档 catalog.xml。

使用 SAXReader 解析 XML 文档 catalog.xml:

SAXReader saxReader = new SAXReader();
 Document document = saxReader.read(inputXml);

SAXReader 包含在 org.dom4j.io 包中。

inputXml 是从 c:/catalog/catalog.xml 创建的 java.io.File。使用 XPath 表达式从article 元素中获得level 节点列表。如果level 属性值是“Intermediate”则改为“Introductory”。

List list = document.selectNodes("//article/@level" );
      Iterator iter=list.iterator();
        while(iter.hasNext()){
            Attribute attribute=(Attribute)iter.next();
               if(attribute.getValue().equals("Intermediate"))
               attribute.setValue("Introductory"); 
       }

获取 article 元素列表,从 article 元素中的 title 元素得到一个迭代器,并修改title 元素的文本。

list = document.selectNodes("//article" );
     iter=list.iterator();
   while(iter.hasNext()){
       Element element=(Element)iter.next();
      Iterator iterator=element.elementIterator("title");
   while(iterator.hasNext()){
   Element titleElement=(Element)iterator.next();
   if(titleElement.getText().equals("Java configuration with XML Schema"))
     titleElement.setText("Create flexible and extensible XML schema");
    }}

通过和 title 元素类似的过程修改 author 元素。

清单 4 所示的示例程序 Dom4JParser.java 用于把 catalog.xml 文档修改成 catalog-modified.xml 文档。

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Attribute;
import java.util.List;
import java.util.Iterator;
import org.dom4j.io.XMLWriter;
import java.io.*;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader; 
public class Dom4JParser{
 public void modifyDocument(File inputXml){
  try{
   SAXReader saxReader = new SAXReader();
   Document document = saxReader.read(inputXml);
   List list = document.selectNodes("//article/@level" );
   Iterator iter=list.iterator();
   while(iter.hasNext()){
    Attribute attribute=(Attribute)iter.next();
    if(attribute.getValue().equals("Intermediate"))
      attribute.setValue("Introductory"); 
       }
   
   list = document.selectNodes("//article/@date" );
   iter=list.iterator();
   while(iter.hasNext()){
    Attribute attribute=(Attribute)iter.next();
    if(attribute.getValue().equals("December-2001"))
      attribute.setValue("October-2002");
       }
   list = document.selectNodes("//article" );
   iter=list.iterator();
   while(iter.hasNext()){
    Element element=(Element)iter.next();
    Iterator iterator=element.elementIterator("title");
      while(iterator.hasNext()){
        Element titleElement=(Element)iterator.next();
        if(titleElement.getText().equals("Java configuration with XML
      Schema"))
        titleElement.setText("Create flexible and extensible XML schema");
                                          }
                                }
    list = document.selectNodes("//article/author" );
    iter=list.iterator();
     while(iter.hasNext()){
     Element element=(Element)iter.next();
     Iterator iterator=element.elementIterator("firstname");
     while(iterator.hasNext()){
      Element firstNameElement=(Element)iterator.next();
      if(firstNameElement.getText().equals("Marcello"))
      firstNameElement.setText("Ayesha");
                                     }
                              }
    list = document.selectNodes("//article/author" );
    iter=list.iterator();
     while(iter.hasNext()){
      Element element=(Element)iter.next();
      Iterator iterator=element.elementIterator("lastname");
     while(iterator.hasNext()){
      Element lastNameElement=(Element)iterator.next();
      if(lastNameElement.getText().equals("Vitaletti"))
      lastNameElement.setText("Malik");
                                  }
                               }
     XMLWriter output = new XMLWriter(
      new FileWriter( new File("c:/catalog/catalog-modified.xml") ));
     output.write( document );
     output.close();
   }
 
  catch(DocumentException e)
                 {
                  System.out.println(e.getMessage());
                            }
  catch(IOException e){
                       System.out.println(e.getMessage());
                    }
 }
 public static void main(String[] argv){
  Dom4JParser dom4jParser=new Dom4JParser();
  dom4jParser.modifyDocument(new File("c:/catalog/catalog.xml"));
                                        }
   }

这一节说明了如何使用 dom4j 中的解析器修改示例 XML 文档。这个解析器不使用 DTD 或者模式验证 XML 文档。如果 XML 文档需要验证,可以解释用 dom4j 与 JAXP SAX 解析器。

 

 

XML的三种方式(DOM,SAX,PULL)

1. DOM

DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的,但是这样一来,如果xml文件很大呢?手机CPU处理能力当然不能与PC机器比,因此在处理效率方面就相对差了,当然这是对于其他方式处理xml文档而言。


2. SAX
SAX是基于事件驱动的。当然android的事件机制是基于回调函数的,在用SAX解析xml文档时候,在读取到文档开始和结束标签时候就会回调一个事件,在读取到其他节点与内容时候也会回调一个事件。

既然涉及到事件,就有事件源,事件处理器。在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法 来解析XML文档,并产生事件。事件处理器是org.xml.sax包中ContentHander、DTDHander、ErrorHandler,以 及EntityResolver这4个接口

需要XmlReader 以及DefaultHandler来配合解析xml。

3.PULL

PULL方式也是基于事件驱动的,读取xml回调方法返回的是数字。

读取到xml的声明返回      START_DOCUMENT
读取到xml的结束返回       END_DOCUMENT 
读取到xml的开始标签返回 START_TAG 
读取到xml的结束标签返回 END_TAG 
读取到xml的文本返回       TEXT

 

package per.lx.xml_parser; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.Serializable; 
import java.util.ArrayList; 
import java.util.List;

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 
 
import org.w3c.dom.Element; 
import org.w3c.dom.NodeList; 
import org.xml.sax.Attributes; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 
import org.xmlpull.v1.XmlPullParser; 
import org.xmlpull.v1.XmlPullParserException; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.util.Xml; 
import android.widget.TextView; 
 
public class XMLParserTestActivity extends Activity { 
 
    private static final String DOM = "DOM parser"; 
    private static final String SAX = "SAX parser"; 
    private static final String PULL = "PULL parser"; 
 
    private String parserType = DOM; 
 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
 
        List<SearchInfo> infos = null; 
        if (DOM.equals(parserType)) { 
            infos = parserByDOM("search.xml"); 
        } else if (SAX.equals(parserType)) { 
            infos = parserBySAX("search.xml"); 
        } else if (PULL.equals(parserType)) { 
            infos = parserByPULL("search.xml"); 
        } 
 
        TextView search = (TextView) findViewById(R.id.search); 
        StringBuilder infoBuilder = new StringBuilder(); 
        infoBuilder.append(" " + parserType + "\n\n"); 
        for (int i = 0; i < infos.size(); i++) { 
            infoBuilder.append(" name : " + infos.get(i).getName() + "\n"); 
            infoBuilder.append(" age : " + infos.get(i).getAge() + "\n"); 
            infoBuilder.append(" introduction : " + infos.get(i).getIntroduction() + "\n"); 
            infoBuilder.append(" url : " + infos.get(i).getUrl() + "\n"); 
            infoBuilder.append("\n"); 
        } 
        search.setText(infoBuilder.toString()); 
    } 
 
    public static class SearchInfo implements Serializable { 
 
        /**
         * 
         */ 
        private static final long serialVersionUID = 1L; 
 
        private String name; 
 
        private int age; 
 
        private String introduction; 
 
        private String url; 
 
        public String getName() { 
            return name; 
        } 
 
        public void setName(String name) { 
            this.name = name; 
        } 
 
        public int getAge() { 
            return age; 
        } 
 
        public void setAge(int age) { 
            this.age = age; 
        } 
 
        public String getIntroduction() { 
            return introduction; 
        } 
 
        public void setIntroduction(String introduction) { 
            this.introduction = introduction; 
        } 
 
        public String getUrl() { 
            return url; 
        } 
 
        public void setUrl(String url) { 
            this.url = url; 
        } 
 
    } 
 
    private static final String SEARCH = "search"; 
    private static final String NAME = "name"; 
    private static final String AGE = "age"; 
    private static final String INTRODUCTION = "introduction"; 
    private static final String URL = "url"; 
 
    /**
     * DOM parse
     * 
     * @param fileName
     * @return
     */ 
    private List<SearchInfo> parserByDOM(String fileName) { 
        List<SearchInfo> infos = new ArrayList<SearchInfo>(); 
        try { 
            // 加载xml文档 
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
            InputStream inputStream = getResources().getAssets().open(fileName); 
            // 找到根节点---searchs 
            NodeList nodes = builder.parse(inputStream).getDocumentElement().getElementsByTagName(SEARCH); 
            // 遍历根节点searchs下的所有子节点 
            for (int i = 0; i < nodes.getLength(); i++) { 
                SearchInfo info = new SearchInfo(); 
                Element searchElement = (Element) nodes.item(i); 
                info.setName(searchElement.getAttribute(NAME)); 
                info.setAge(Integer.parseInt(searchElement.getAttribute(AGE))); 
                Element introduction = (Element) searchElement.getElementsByTagName(INTRODUCTION).item(0); 
                info.setIntroduction(introduction.getFirstChild().getNodeValue()); 
                Element url = (Element) searchElement.getElementsByTagName(URL).item(0); 
                info.setUrl(url.getFirstChild().getNodeValue()); 
                infos.add(info); 
            } 
        } catch (ParserConfigurationException e) { 
            e.printStackTrace(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } catch (SAXException e) { 
            e.printStackTrace(); 
        } 
        return infos; 
    } 
 
    /**
     * SAX parse
     * 
     * @param fileName
     * @return
     */ 
    private List<SearchInfo> parserBySAX(String fileName) { 
        List<SearchInfo> infos = null; 
        try { 
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 
            XMLReader reader = parser.getXMLReader(); 
            SearchHander hander = new SearchHander(); 
            reader.setContentHandler(hander); 
            reader.parse(new InputSource(getAssets().open(fileName))); 
            infos = hander.getSearchInfos(); 
        } catch (ParserConfigurationException e) { 
            e.printStackTrace(); 
        } catch (SAXException e) { 
            e.printStackTrace(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
        return infos; 
    } 
 
    private class SearchHander extends DefaultHandler { 
 
        private SearchInfo info; 
        private List<SearchInfo> infos = new ArrayList<SearchInfo>(); 
 
        private boolean isIntroduction = false; 
        private boolean isURL = false; 
 
        public List<SearchInfo> getSearchInfos() { 
            return infos; 
        } 
 
        // 开始读取标签 
        public void startElement(String uri, String localName, String qName, Attributes attributes) { 
            String tagName = localName.length() != 0 ? localName : qName; 
            tagName = tagName.toLowerCase().trim(); 
            // 读取的是Search标签开始,则实例化SearchInfo 
            if (tagName.equals(SEARCH)) { 
                info = new SearchInfo(); 
                info.setName(attributes.getValue(NAME)); 
                info.setAge(Integer.parseInt(attributes.getValue(AGE))); 
            } 
            // 读取其他节点 
            if (tagName.equals(INTRODUCTION)) { 
                isIntroduction = true; 
            } else if (tagName.equals(URL)) { 
                isURL = true; 
            } 
        } 
 
        // 结束标签 
        public void endElement(String uri, String localName, String qName) { 
            String tagName = localName.length() != 0 ? localName : qName; 
            tagName = tagName.toLowerCase().trim(); 
 
            // 读取的是Search标签结束,则把search添加进集合中 
            if (tagName.equals(SEARCH)) { 
                infos.add(info); 
            } 
            // 读取其他节点 
            if (tagName.equals(INTRODUCTION)) { 
                isIntroduction = false; 
            } else if (tagName.equals(URL)) { 
                isURL = false; 
            } 
        } 
 
        // 读取到节点内容时的回调 
        public void characters(char[] ch, int start, int length) { 
            if (isIntroduction) { 
                info.setIntroduction(new String(ch, start, length)); 
            } else if (isURL) { 
                info.setUrl(new String(ch, start, length)); 
            } 
        } 
 
    } 
 
    /**
     * Pull parse
     * 
     * @param fileName
     * @return
     */ 
    private List<SearchInfo> parserByPULL(String fileName) { 
        List<SearchInfo> infos = new ArrayList<SearchInfo>(); 
        XmlPullParser xmlParser = Xml.newPullParser(); 
        InputStream inputStream = null; 
        try { 
            inputStream = getResources().getAssets().open(fileName); 
            xmlParser.setInput(inputStream, "utf-8"); 
            int evtType = xmlParser.getEventType(); 
            SearchInfo info = null; 
            while (evtType != XmlPullParser.END_DOCUMENT) { 
                switch (evtType) { 
                case XmlPullParser.START_TAG: 
                    String tag = xmlParser.getName(); 
                    // 如果是search标签开始,则实例化对象 
                    if (tag.equalsIgnoreCase(SEARCH)) { 
                        info = new SearchInfo(); 
                        // 取出search标签中的属性值 
                        info.setName(xmlParser.getAttributeValue(null, NAME)); 
                        info.setAge(Integer.parseInt(xmlParser.getAttributeValue(null, AGE))); 
                    } else if (info != null) { 
                        if (tag.equalsIgnoreCase(INTRODUCTION)) { 
                            info.setIntroduction(xmlParser.nextText()); 
                        } else if (tag.equalsIgnoreCase(URL)) { 
                            info.setUrl(xmlParser.nextText()); 
                        } 
                    } 
                    break; 
                case XmlPullParser.END_TAG: 
                    // 如果遇到search标签结束,则把search对象添加进集合中 
                    if (xmlParser.getName().equalsIgnoreCase(SEARCH) && info != null) { 
                        infos.add(info); 
                        info = null; 
                    } 
                    break; 
                default: 
                    break; 
                } 
                // 如果xml没有结束,则导航到下一个river节点 
                evtType = xmlParser.next(); 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } catch (XmlPullParserException e) { 
            e.printStackTrace(); 
        } 
        return infos; 
    } 
 

 

search.xml


<?xml version="1.0" encoding="utf-8"?> 
<searchs> 
 
    <search 
        name="google" age="14" > 
        <introduction>Hi, This is google search!</introduction> 
        <url>http://www.google.com</url> 
    </search> 
 
    <search 
        name="baidu" age="12" > 
        <introduction>Hi, This is baidu search!</introduction> 
        <url>http://www.baidu.com</url> 
    </search> 
 
    <search 
        name="biying" age="3" > 
        <introduction>Hi, This is biying search!</introduction> 
        <url>http://www.biying.com</url> 
    </search> 
 
</searchs>

 

DOM4J_xpath 操作简介

1、DOM4J简介 
DOM4J是 dom4j.org 出品的一个开源 XML 解析包。DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。
    DOM4J 使用起来非常简单。只要你了解基本的 XML-DOM 模型,就能使用。
    Dom:把整个文档作为一个对象。
  DOM4J 最大的特色是使用大量的接口。它的主要接口都在org.dom4j里面定义:

Attribute
定义了 XML 的属性。
Branch
指能够包含子节点的节点。如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为
CDATA
定义了 XML CDATA 区域
CharacterData
是一个标识接口,标识基于字符的节点。如CDATA,Comment, Text.
Comment
定义了 XML 注释的行为
Document
定义了XML 文档
DocumentType
定义 XML DOCTYPE 声明
Element
定义XML 元素
ElementHandler
定义了Element 对象的处理器
ElementPath
被 ElementHandler 使用,用于取得当前正在处理的路径层次信息
Entity
定义 XML entity
Node
为dom4j中所有的XML节点定义了多态行为
NodeFilter
定义了在dom4j 节点中产生的一个滤镜或谓词的行为(predicate)
ProcessingInstruction
定义 XML 处理指令
Text
定义 XML 文本节点
Visitor
用于实现 Visitor模式
XPath
在分析一个字符串后会提供一个 XPath 表达式

接口之间的继承关系如下:
interface java.lang.Cloneable
    interface org.dom4j.Node
           interface org.dom4j.Attribute
           interface org.dom4j.Branch
                  interface org.dom4j.Document
                  interface org.dom4j.Element
           interface org.dom4j.CharacterData
                  interface org.dom4j.CDATA
                  interface org.dom4j.Comment
                  interface org.dom4j.Text
           interface org.dom4j.DocumentType
           interface org.dom4j.Entity
           interface org.dom4j.ProcessingInstruction
 
 
2、XML文档操作1
2.1、读取XML文档:
     读写XML文档主要依赖于org.dom4j.io包,有DOMReader和SAXReader两种方式。因为利用了相同的接口,它们的调用方式是一样的。
Java代码  
public static Document load(String filename) { 
  
Document document = null;  
  
try {  
  
    SAXReader saxReader = new SAXReader();  
  
   document = saxReader.read(new File(filename));  //读取XML文件,获得document对象  
  
} catch (Exception ex) {  
 
    ex.printStackTrace();  
 
}  
 
return document;
}
或Java代码  
public static Document load(URL url) {  
  
   Document document = null;  
  
   try {  
  
   SAXReader saxReader = new SAXReader();  
  
         document = saxReader.read(url);  //读取XML文件,获得document对象  
 
  } catch (Exception ex) {  
  
         ex.printStackTrace();  
  
  }  
  
   return document;  
  
}   
 
//读取指定的xml文件之后返回一个Document对象,这个对象代表了整个XML文档,用于各种Dom运算。执照XML文件头所定义的编码来转换。 
 
2.2、获取根节点
根节点是xml分析的开始,任何xml分析工作都需要从根开始
Xml xml = new Xml();
Doument dom = xml.load(path + "/" + file);
Element root = dom.getRootElement();
2.3、新增一个节点以及其下的子节点与数据
Element menuElement = root.addElement("menu");
Element engNameElement = menuElement.addElement("engName");
engNameElement.setText(catNameEn);
Element chiNameElement = menuElement.addElement("chiName");
chiNameElement.setText(catName);
2.4、 写入XML文件 
注意文件操作的包装类是乱码的根
Java代码  
public static boolean doc2XmlFile(Document document, String filename) {  
    boolean flag = true;  
    try {  
        XMLWriter writer = new XMLWriter( new OutputStreamWriter(new FileOutputStream(filename),"UTF-8")); 
        writer.write(document);  
        writer.close();  
    } catch (Exception ex) {  
        flag = false;  
        ex.printStackTrace();  
    }  
    System.out.println(flag);  
    return flag;  
} 
 Dom4j通过XMLWriter将Document对象表示的XML树写入指定的文件,并使用OutputFormat格式对象指定写入的风格和编码方法。调用OutputFormat. createPrettyPrint()方法可以获得一个默认的pretty print风格的格式对象。对OutputFormat对象调用setEncoding()方法可以指定XML文件的编码方法。 
2. 5、 遍历xml节点
       对Document对象调用getRootElement()方法可以返回代表根节点的Element对象。拥有了一个Element对象后,可以对该对象调用elementIterator()方法获得它的子节点的Element对象们的一个迭代器。使用(Element)iterator.next()方法遍历一个iterator并把每个取出的元素转化为Element类型。
2.6、创建xml文件
public static void main(String args[]){
String fileName="c:/text.xml";
Document document=DocumentHelper.createDocument();//建立document对象,用来操作xml文件
Element booksElement=document.addElement("books");//建立根节点
booksElement.addComment("This is a test for dom4j ");//加入一行注释
Element bookElement=booksElement.addElement("book");//添加一个book节点
bookElement.addAttribute("show","yes");//添加属性内容
Element titleElement=bookElement.addElement("title");//添加文本节点
titleElement.setText("ajax in action");//添加文本内容
try{
XMLWriter writer=new XMLWriter(new FileWriter(new File(fileName)));
writer.write(document); 
writer.close();
}catch(Exception e){
e.printStackTrace();
}
}
2.7、修改节点属性
public static void modifyXMLFile() {
String oldStr = "c:/text.xml";
String newStr = "c:/text1.xml";
Document document = null;
//修改节点的属性
try {
SAXReader saxReader = new SAXReader(); // 用来读取xml文档
document = saxReader.read(new File(oldStr)); // 读取xml文档
List list = document.selectNodes("/books/book/@show");// 用xpath查找节点book的属性
Iterator iter = list.iterator();
while (iter.hasNext()) {
Attribute attribute = (Attribute) iter.next();
if (attribute.getValue().equals("yes")) 
    attribute.setValue("no");
}
} catch (Exception e) {
    e.printStackTrace();
}
//修改节点的内容
try {
SAXReader saxReader = new SAXReader(); // 用来读取xml文档
document = saxReader.read(new File(oldStr)); // 读取xml文档
List list = document.selectNodes("/books/book/title");// 用xpath查找节点book的内容
Iterator iter = list.iterator();
while (iter.hasNext()) {
Element element = (Element) iter.next();
element.setText("xxx");// 设置相应的内容
}
} catch (Exception e) {
    e.printStackTrace();
}
 
try {
XMLWriter writer = new XMLWriter(new FileWriter(new File(newStr)));
writer.write(document);
writer.close();
} catch (Exception ex) {
    ex.printStackTrace();
}
}
2.8、删除节点
public static void removeNode() {
String oldStr = "c:/text.xml";
String newStr = "c:/text1.xml";
Document document = null;
try {
SAXReader saxReader = new SAXReader();// 用来读取xml文档
document = saxReader.read(new File(oldStr));// 读取xml文档
List list = document.selectNodes("/books/book");// 用xpath查找对象
Iterator iter = list.iterator();
while (iter.hasNext()) {
Element bookElement = (Element) iter.next();
// 创建迭代器,用来查找要删除的节点,迭代器相当于指针,指向book下所有的title节点
Iterator iterator = bookElement.elementIterator("title");
while (iterator.hasNext()) {
Element titleElement = (Element) iterator.next();
if (titleElement.getText().equals("ajax in action")) {
bookElement.remove(titleElement);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
XMLWriter writer = new XMLWriter(new FileWriter(new File(newStr)));
writer.write(document);
writer.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
 
2、XML文档操作2
2.1、Document对象相关        
1、读取XML文件,获得document对象.      
       SAXReader reader = new SAXReader();        
      Document   document = reader.read(new File("input.xml"));      
2、解析XML形式的文本,得到document对象.       
             String text = "<members></members>"; 
             Document document = DocumentHelper.parseText(text);      
3、主动创建document对象.       
             Document document = DocumentHelper.createDocument();  
             Element root = document.addElement("members");// 创建根节点      
2.2、节点相关        
1、获取文档的根节点.       
Element rootElm = document.getRootElement();      
2、取得某节点的单个子节点.       
Element memberElm=root.element("member");// "member"是节点名        
3.取得节点的文字       
       String text=memberElm.getText();    
       String text=root.elementText("name");这个是取得根节点下的name字节点的文字.       
4.取得某节点下指定名称的所有节点并进行遍历.       
 
Java代码  
List nodes = rootElm.elements("member");        
for (Iterator it = nodes.iterator(); it.hasNext();) {        
    Element elm = (Element) it.next();        
   // do something        
}        
 
5.对某节点下的所有子节点进行遍历.       
Java代码  
for(Iterator it=root.elementIterator();it.hasNext();){        
             Element element = (Element) it.next();        
            // do something        
}        
  
6.在某节点下添加子节点.      
Element ageElm = newMemberElm.addElement("age");      
7.设置节点文字.       
ageElm.setText("29");      
8.删除某节点.       
parentElm.remove(childElm);    // childElm是待删除的节点,parentElm是其父节点      
9.添加一个CDATA节点.      
         Element contentElm = infoElm.addElement("content");     
         contentElm.addCDATA(diary.getContent());     
      
2.3、属性相关.      
1.取得节点的指定的属性      
             Element root=document.getRootElement();          
             Attribute attribute=root.attribute("size");    // 属性名name      
2.取得属性的文字       
    String text=attribute.getText();    
String text2=root.element("name").attributeValue("firstname");
//这个是取得根节点下name字节点的firstname属性的值.      
3.遍历某节点的所有属性      
Element root=document.getRootElement();
for(Iterator it=root.attributeIterator();it.hasNext();){
Attribute attribute = (Attribute) it.next();
String text=attribute.getText();
System.out.println(text);
}
4.设置某节点的属性和文字.      
newMemberElm.addAttribute("name", "sitinspring");    
5.设置属性的文字       
             Attribute attribute=root.attribute("name");      
             attribute.setText("sitinspring");      
6.删除某属性       
             Attribute attribute=root.attribute("size");// 属性名name      
             root.remove(attribute);      
2.4、将文档写入XML文件.     
1.文档中全为英文,不设置编码,直接写入.      
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));      
writer.write(document);      
writer.close();      
2.文档中含有中文,设置编码格式再写入.     
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("GBK");    // 指定XML编码
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"),format);
writer.write(document);
writer.close();
2.5、字符串与XML的转换      
1.将字符串转化为XML      
String text = "<members> <member>sitinspring</member> </members>";      
Document document = DocumentHelper.parseText(text);      
2.将文档或节点的XML转化为字符串.     
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
Element root=document.getRootElement();
String docXmlText=document.asXML();
String rootXmlText=root.asXML();
Element memberElm=root.element("member");
String memberXmlText=memberElm.asXML();
 
3、dom4j的事件处理模型涉及的类和接口:
3.1、类:SAXReader
         public voidaddHandler(String path,ElementHandler handler)
     当解析到path指定的路径时,将调用参数handler指定的处理器。针对不同的节点可以添加多个handler实例。或者调用默认的Handler setDefaultHandler(ElementHandler handler);
3.2、接口ElementHandler
         public void onStart(ElementPath path)
     该方法在解析到元素的开始标签时被调用。
         public voidonEnd(ElementPath path)
     该方法在解析到元素的结束标签时被调用
3.3、接口:ElementPath(假设有参数:ElementPath path)
         public voidaddHandler(String path,ElementHandler)
     该方法与SAXReader类中的addHandler()方法的作用相同。路径path可以是绝对路径(路径以/开头),也可以是相对路径(假设是当前路径的子节点路径)。
         public voidremoveHandler(String path)
     移除指定路径上的ElementHandler实例。路径可以是相对路径,也可以是绝对路径。
         public StringgetPath()
     该方法得到当前节点的路径。该方法返回的是完整的绝对路径
         public ElementgetCurrent()
     该方法得到当前节点。
3.3、Element类 

getQName()
元素的QName对象
getNamespace()
元素所属的Namespace对象
getNamespacePrefix()
元素所属的Namespace对象的prefix
getNamespaceURI()
元素所属的Namespace对象的URI
getName()
元素的local name
getQualifiedName()
元素的qualified name
getText()
元素所含有的text内容,如果内容为空则返回一个空字符串而不是null
getTextTrim()
元素所含有的text内容,其中连续的空格被转化为单个空格,该方法不会返回null
attributeIterator()
元素属性的iterator,其中每个元素都是Attribute对象
attributeValue()
元素的某个指定属性所含的值
elementIterator()
元素的子元素的iterator,其中每个元素都是Element对象
element()
元素的某个指定(qualified name或者local name)的子元素
elementText()
元素的某个指定(qualified name或者local name)的子元素中的text信息
getParent
元素的父元素
getPath()
元素的XPath表达式,其中父元素的qualified name和子元素的qualified name之间使用"/"分隔
isTextOnly()
是否该元素只含有text或是空元素
isRootElement()
是否该元素是XML树的根节点

 
3.4、类DocumentHelper 
DocumentHelper 是用来生成生成 XML 文档的工厂类
4、通过xpath查找指定的节点
       采用xpath查找需要引入jaxen-xx-xx.jar,否则会报java.lang.NoClassDefFoundError: org/jaxen/JaxenException异常。
 
  List list=document.selectNodes("/books/book/@show");
4.1、 xpath语法
1、选取节点
XPath 使用路径表达式在 XML 文档中选取节点,节点是沿着路径或者 step 来选取的。
常见的路径表达式:

表达式
描述
nodename
选取当前节点的所有子节点
/
从根节点选取
//
从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
.
选取当前节点
..
选取当前节点的父节点
@
选取属性

实例

路径表达式
结果
bookstore
选取 bookstore 元素的所有子节点
/bookstore
选取根元素 bookstore
bookstore/book
选取bookstore 下名字为 book的所有子元素。
//book
选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book
选取bookstore 下名字为 book的所有后代元素,而不管它们位于 bookstore 之下的什么位置。
//@lang
选取所有名为 lang 的属性。

2、谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
实例
常见的谓语的一些路径表达式:

路径表达式
结果
/bookstore/book[1]
选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]
选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]
选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3]
选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]
选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng']
选取所有 title 元素,要求这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00]
选取所有 bookstore 元素的 book 元素,要求book元素的子元素 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title
选取所有 bookstore 元素中的 book 元素的 title 元素,要求book元素的子元素 price 元素的值须大于 35.00

3、选取未知节点
XPath 通配符可用来选取未知的 XML 元素。

通配符
描述
*
匹配任何元素节点
@*
匹配任何属性节点
node()
匹配任何类型的节点

实例

路径表达式
结果
/bookstore/*
选取 bookstore 元素的所有子节点
//*
选取文档中的所有元素
//title[@*]
选取所有带有属性的 title 元素。

4、选取若干路径
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
实例

路径表达式
结果
//book/title | //book/price
选取所有 book 元素的 title 和 price 元素。
//title | //price
选取所有文档中的 title 和 price 元素。
/bookstore/book/title|//price
选取所有属于 bookstore 元素的 book 元素的 title 元素,以及文档中所有的 price 元素。

 
5、XPath 轴
轴可定义某个相对于当前节点的节点集。

轴名称
结果
ancestor
选取当前节点的所有先辈(父、祖父等)
ancestor-or-self
选取当前节点的所有先辈(父、祖父等)以及当前节点本身
attribute
选取当前节点的所有属性
child
选取当前节点的所有子元素。
descendant
选取当前节点的所有后代元素(子、孙等)。
descendant-or-self
选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following
选取文档中当前节点的结束标签之后的所有节点。
namespace
选取当前节点的所有命名空间节点
parent
选取当前节点的父节点。
preceding
选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling
选取当前节点之前的所有同级节点。
self
选取当前节点。

6、路径
Ø  位置路径表达式
位置路径可以是绝对的,也可以是相对的。
绝对路径起始于正斜杠( / ),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割:
Ø  绝对位置路径:
/step/step/...
Ø  相对位置路径:
step/step/...
每个步均根据当前节点集之中的节点来进行计算。
Ø  步(step)包括:
轴(axis):定义所选节点与当前节点之间的树关系
节点测试(node-test):识别某个轴内部的节点
零个或者更多谓语(predicate):更深入地提炼所选的节点集
步的语法:轴名称::节点测试[谓语]
实例

例子
结果
child::book
选取所有属于当前节点的子元素的 book 节点
attribute::lang
选取当前节点的 lang 属性
child::*
选取当前节点的所有子元素
attribute::*
选取当前节点的所有属性
child::text()
选取当前节点的所有文本子节点
child::node()
选取当前节点的所有子节点
descendant::book
选取当前节点的所有 book 后代
ancestor::book
选择当前节点的所有 book 先辈
ancestor-or-self::book
选取当前节点的所有book先辈以及当前节点(假如此节点是book节点的话)
child::*/child::price
选取当前节点的所有 price 孙。

 
7、XPath 运算符

运算符
描述
实例
返回值
|
计算两个节点集
//book | //cd
返回所有带有 book 和 ck 元素的节点集
+
加法
6 + 4
10
-
减法
6 - 4
2
*
乘法
6 * 4
24
div
除法
8 div 4
2
=
等于
price=9.80
如果 price 是 9.80,则返回 true。
如果 price 是 9.90,则返回 fasle。
!=
不等于
price!=9.80
如果 price 是 9.90,则返回 true。
如果 price 是 9.80,则返回 fasle。
小于
price<9.80
如果 price 是 9.00,则返回 true。
如果 price 是 9.90,则返回 fasle。
<=
小于或等于
price<=9.80
如果 price 是 9.00,则返回 true。
如果 price 是 9.90,则返回 fasle。
大于
price>9.80
如果 price 是 9.90,则返回 true。
如果 price 是 9.80,则返回 fasle。
>=
大于或等于
price>=9.80
如果 price 是 9.90,则返回 true。
如果 price 是 9.70,则返回 fasle。
or
price=9.80 or price=9.70
如果 price 是 9.80,则返回 true。
如果 price 是 9.50,则返回 fasle。
and
price>9.00 and price<9.90
如果 price 是 9.80,则返回 true。
如果 price 是 8.50,则返回 fasle。
mod
计算除法的余数
5 mod 2
1

 
 
 

 

 

读取和保存XML方法简单总结

read xml
1.dom4j
SAXReader sax = new SAXReader();
sax.setEncoding("UTF-8");//记得与XML文件实际的编码一致.
Document document = saxReader.read(inputXml);//inputXml文件路径.

2.jdom
 SAXBuilder buider = new SAXBuilder();
Document document = saxReader.read(inputXml);//inputXml是FILE的对象.


save xml 
1.dom4j方法1
OutputFormat format = OutputFormat.createPrettyPrint();
fomat.setEncoding("UTF-8");
//outXmlPath是保存XML的文件全路径
XMLWrite write = new XMLWriter(new FileWrite(outXmlPath),format);
writer.write(document); 
writer.close(); 

2.dom4j方法2
//outXmlPath是保存XML的文件全路径
XMLWriter writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream

(outXmlPath),"UTF-8"));
writer.write(document); 
writer.close(); 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值