• Java 读取 xml 文件


    <?xml version="1.0" encoding="UTF-8"?>
    <bookstore>
    <book id="1">
    <name>冰与火之歌</name>
    <author>乔治马丁</author>
    <year>2014</year>
    <price>89</price>
    </book>
    </bookstore>

    这是一个简单的xml文件,根节点是bookstore,book是bookstroe的子节点,book节点有属性id ,也有子节点name author year price。子节点name author year price没有属性 ,只有值。

    1、DOM: Document Object Model 文档对象模型

      DOM解析会一次性的将xml读取到内存中,并形成一个DOM树,如果xml非常大会浪费时间,对内存性能要求高。

      优点:形成树结构,直观好理解,代码更易编写,解析过程中树结构保留在内存中,方便修改。

        缺点:当xml文件较大时,对内存耗费比较大,容易影响解析性能并造成内存溢出。

    package com.zhao.dom;
    
    import java.io.IOException;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NamedNodeMap;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    
    public class DOMTest {
    /**
    * 应用DOM方式解析XML DOM: Document Object Model 文档对象模型
    * DOM解析会一次性的将xml读取到内存中,并形成一个dom树,如果xml非常大会浪费时间,对内存性能要求高
    * @author zhao
    * @param args
    */
    public static void main(String[] args) {
    // 创建一个DocumentBuilderFactory的对象
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    try {
    // 创建一个DocumentBuilder的对象
    DocumentBuilder builder = factory.newDocumentBuilder();
    // 通过DocumentBuilder对象的parse方法加载bookstroe.xml文件到当前项目下
    Document document = builder.parse("bookstore.xml");
    // 获取所有book节点的集合
    NodeList bookList = document.getElementsByTagName("book");
    // 通过NodeList的getLength方法可以获取boolList的长度
    System.out.println("===========" + bookList.getLength() + "===========");
    // 遍历每一个book节点
    for (int i = 0; i < bookList.getLength(); i++) {
    
    // 已经知道节点元素的属性名:
    /*
    * Element element=(Element) bookList.item(i); String
    * id=element.getAttribute("id"); System.out.println(id);
    */
    // 不知道节点元素的属性名:
    // 通过item(i)方法获取一个book节点,NodeList的索引值从0开始
    Node book = bookList.item(i);
    // 获取book节点的所有属性集合
    NamedNodeMap map = book.getAttributes();
    // 遍历book的属性
    System.out.println("第" + (i + 1) + "本书共有" + map.getLength() + "个属性");
    for (int j = 0; j < map.getLength(); j++) {
    // 通过item(j)方法获取book节点的某一个属性
    Node attr = map.item(j);
    // 获取属性名和属性值
    System.out.println(attr.getNodeName() + "=" + attr.getNodeValue());
    }
    // 解析book节点的子节点
    NodeList childNode = book.getChildNodes();
    System.out.println(childNode.getLength());
    
    /*
    * 通过book元素的getChildNodes()得到所有子节点的集合,需要注意的是,在DOM的读取中,
    * 会将空格和回车看成是text节点类型,因此需要注意区分开。通过item(index)遍历所有子节点,通过item(
    * index)的getNodeName()方法还来获取子节点的名字,而获取它的属性值时,
    * 要注意直接使用getNodeValue()得到的是标签的值(一般是空)因此可以使用两种方法:
    * 1.使用item(index).getFirstNode().getNodeValue()来返回值(<name>冰与火之歌
    * </name>中冰与火之歌是name的子节点,而且这个节点类型是text,现在我们有节点name,
    * 只需要找到它的第一个节点的节点值便可以了)
    * 2.使用item(index).getTextContent()来返回属性值
    * 上面两种方法的区别在于在一个标签中是否包含的其他的子标签,如果有的话,那么第1个方法就仍得到null,
    * 第二个方法会返会将自标签的内容一起获得。
    */
    // 遍历childNode获取每个节点的节点名和节点值
    for (int j = 0; j < childNode.getLength(); j++) {
    Node child = childNode.item(j);
    // System.out.println(child.getNodeName());
    // 区分test类型的node和element类型的node
    if (child.getNodeType() == Node.ELEMENT_NODE) {
    System.out.println(child.getNodeName() + "=" + child.getTextContent());
    }
    }
    
    }
    
    } catch (ParserConfigurationException e) {
    e.printStackTrace();
    } catch (SAXException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    
    }

    分析:

      DOM使用DocumenBuilder的parse方法加载xml文件到当前目录下,parse是分析的意思。首先会用到工厂模式,先生成DocumentBuilderFactory,再由其生成DocumentBuilder,DocumentBuilder.parse会返回一个Document对象,这是xml文件到Document的过程,无论使用DOM ,SAX,JDOM,DOM4J,此步骤大同小异。

      Document就是上面写好的xml文件。

      常用节点类型       nodeName      nodeValue

      Element      element Name      null

      Attr          属性名称                   属性值

      Test          #text        节点内容

      在此document中,bookstroe是节点,book是节点,name是节点,id也是节点。类似于HTML,document.getElementsByTagName("book")可以得到所有book element,book节点有属性节点Attr,有子节点Element,也有空格Text。Node是所有节点的总称,在未知节点类型时使用Node,所有有book node。

      book node的getAttributes返回属性节点的集合NamedNodeMap,进而得到其每个属性节点node,由上述可得属性名称是node.getNodeName,属性值是node.getNodeValue。

     book.getChildNodes得到子节点集合,这里我们依旧用Node此时node是element或Text,判断child.getNodeType() == Node.ELEMENT_NODE才是我们需要的子节点,对

    <name>冰与火之歌</name>而言,node是name,类型是element,而element的NodeValue却不是冰与火之歌,而是null。冰与火之歌是node的子节点text。故node.getFirstNode().getNodeValue()才是我们需要的结果。

    2:SAX

      优点:采用事件驱动模式,对内存耗费比较小,适用于只需要处理xml数据时。

      缺点:不易编码,很难同时访问同一个xml中的多处不通过数据

    package com.zhao.sax;
    
    import java.io.IOException;
    
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    public class SAXTest {
    /**
    * 应用SAX方式解析XML
    * sax解析是基于事件的解析,每解析一部分就会触发saxHandler的具体方法
    * @author zhao
    * @param args
    */
    public static void main(String[] args) {
    // 获取一个SAXParserFactory的实例
    SAXParserFactory factory = SAXParserFactory.newInstance();
    try {
    // 通过factory获取SAXParser实例
    SAXParser saxParser = factory.newSAXParser();
    // 创建SAXHandler对象
    SAXHandler handler = new SAXHandler();
    saxParser.parse("bookstore.xml", handler);
    
    } catch (ParserConfigurationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (SAXException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    
     

    ----------------------

    package com.zhao.sax;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    import com.zhao.entity.Book;
    
    /**
    * SAXParserHandler类的执行顺序为:startDocument()开始Xml解析--->第一行,以后每行的执行顺序为——>
    * startElement()---characters()--->endElemnet()---->到最后一行的
    * <bookstore>---->endDcunment()。
    * 
    * @author zhao
    *
    */
    public class SAXHandler extends DefaultHandler {
    private int bookIndex = 0;
    private Book book;
    private String value=null;
    private List<Book> books=new ArrayList<Book>();
    
    /**
    * 用于标识解析开始
    */
    @Override
    public void startDocument() throws SAXException {
    // TODO Auto-generated method stub
    super.startDocument();
    System.out.println("SAX解析开始");
    }
    
    /**
    * 用于标识解析结束
    */
    @Override
    public void endDocument() throws SAXException {
    // TODO Auto-generated method stub
    super.endDocument();
    System.out.println("SAX解析结束");
    for (Book book : books) {
    System.out.println(book);
    }
    }
    
    /**
    * 用来遍历xml文件的开始标签 在开始时可用知道属性
    */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    // 调用DefaultHandler类的startElement方法
    super.startElement(uri, localName, qName, attributes);
    // 开始解析book元素的属性
    if ("book".equals(qName)) {
    bookIndex++;
    System.out.println(bookIndex + "本书开始");
    
    book=new Book();
    
    // 已知book元素的下属性的名称,根据属性名称获取属性值
    // String id=attributes.getValue("id");
    // System.out.println("id: "+id);
    // 不知道book元素下的属性名称,以及个数
    for (int i = 0; i < attributes.getLength(); i++) {
    System.out.println(attributes.getQName(i) + ": " + attributes.getValue(i));
    if ("id".equals(attributes.getQName(i))) {
    book.setId(attributes.getValue(i));
    }
    }
    } else if (!"book".equals(qName) && !"bookstore".equals(qName)) {
    System.out.print(qName);
    }
    }
    
    /**
    * 用来遍历xml文件的结束标签
    */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
    // TODO Auto-generated method stub
    super.endElement(uri, localName, qName);
    if ("book".equals(qName)) {
    System.out.println(bookIndex + "本书结束");
    books.add(book);
    book=null;
    value=null;
    }
    else if (!"bookStore".equals(qName)&&!"book".equals(qName)) {
    if ("name".equals(qName)) {
    book.setName(value);
    }
    else if ("author".equals(qName)) {
    book.setAuthor(value);
    }
    else if("year".equals(qName)){
    book.setYear(value);
    }
    else if ("price".equals(qName)) {
    book.setPrice(value);
    }
    else if ("language".equals(qName)) {
    book.setLanguage(value);
    }
    }
    
    }
    
    /**
    * 
    * @param ch
    * @param start
    * @param length
    * @throws SAXException
    */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
    // TODO Auto-generated method stub
    super.characters(ch, start, length);
    value = new String(ch, start, length).trim();
    if (!value.equals("")) {
    System.out.println(value);
    }
    
    }
    }

    分析:

      SAX使用SAXParser的parse方法解析xml,也是通过SAXParserFactory生成SAXParser。不同于DOMde 节点,sax采用事件驱动,要重写DefaultHandler类,在此类中指明解析xml的过程。

      重写DefaultHandler的startDocument endDocument startElement endElement characters方法。

      解析顺序为:

      startDocument()开始xml解析--》startDocument()开始<bookstore>--》startDocument()开始<book>--》startDocument()开始<name>--》~~~endDocument。

      以<>开始,以</>结束,事件驱动,读到标签开始就是startElement,读到标签结束就是endElement。在二者之间是在characters中读内容。

    3:JDOM

      仅适用具体类而不适用接口,API大量使用了Colletions类

    package com.zhao.jdom;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.List;
    
    import org.jdom2.Attribute;
    import org.jdom2.Document;
    import org.jdom2.Element;
    import org.jdom2.JDOMException;
    import org.jdom2.input.SAXBuilder;
    
    import com.zhao.entity.Book;
    
    public class JDOMTest {
    /**
    * 应用JDOM方式解析xml
    * 
    * @author zhao
    * @param args
    */
    public static void main(String[] args) {
    // 准备工作
    // 1:创建一个SAXBuilder对象
    SAXBuilder saxBuilder = new SAXBuilder();
    InputStream inputStream;
    try {
    // 创建一个输入流,把xml文件加载到输入流
    inputStream = new FileInputStream("bookstore.xml");
    InputStreamReader streamReader = new InputStreamReader(inputStream, "UTF-8");
    // 通过saxBuilder的build方法,将输入流加载到saxBuilder中
    Document doucment = saxBuilder.build(streamReader);
    // 通过document对象获取xml文件的根节点
    Element rootElement = doucment.getRootElement();
    // 获取根节点下的子节点的List集合
    List<Element> bookList = rootElement.getChildren();
    // 继续进行解析
    for (Element element : bookList) {
    Book book = new Book();
    System.out.println("开始解析" + (bookList.indexOf(element) + 1));
    // Attribute id=element.getAttribute("id");
    // System.out.println(id.getName()+" "+id.getValue());
    // 解析book的属性
    List<Attribute> attributes = element.getAttributes();
    for (Attribute attribute : attributes) {
    System.out.println(attribute.getName() + " " + attribute.getValue());
    if ("id".equals(attribute.getName())) {
    book.setId(attribute.getValue());
    }
    }
    // 对book节点的子节点的节点名和节点值的遍历
    List<Element> bookChilds = element.getChildren();
    for (Element child : bookChilds) {
    System.out.println(child.getName() + " " + child.getValue());
    if ("name".equals(child.getName())) {
    book.setName(child.getValue());
    }
    if ("author".equals(child.getName())) {
    book.setAuthor(child.getValue());
    }
    if ("year".equals(child.getName())) {
    book.setYear(child.getValue());
    }
    if ("price".equals(child.getName())) {
    book.setPrice(child.getValue());
    }
    if ("language".equals(child.getName())) {
    book.setLanguage(child.getValue());
    }
    }
    System.out.println(book);
    }
    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (JDOMException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    
    }

    4:DOM4J    DOM FOR JAVA

      JDOM的一种智能分之,它合并了许多超出基本xml文档表示的功能,使用接口和抽象基本类方法,是一个优秀的Java xml API,具有性能优异,灵活性好,功能强大和极端易用使用的特点。

    package com.zhao.dom4j;
    
    import java.io.File;
    import java.util.Iterator;
    import java.util.List;
    
    import org.dom4j.Attribute;
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    public class DOM4JTest {
    /**
    * 应用DOM4J解析xml
    * 
    * @author zhao
    * @param args
    */
    public static void main(String[] args) {
    // 创建SAXReader的reader
    SAXReader saxReader = new SAXReader();
    try {
    // 通过reader的read方法加载xml文件,获取document对象
    Document document = saxReader.read(new File("bookstore.xml"));
    // 通过document对象获取根节点bookstore
    Element bookStore = document.getRootElement();
    //通过element对象的elementIterator方法获取迭代器
    Iterator iterator = bookStore.elementIterator();
    //遍历迭代器,获取根节点中的信息(书籍)
    while (iterator.hasNext()) {
    System.out.println("开始遍历");
    Element book = (Element) iterator.next();
    //获取book的属性名和属性值
    List<Attribute> attributes=book.attributes();
    for (Attribute attribute : attributes) {
    System.out.println(attribute.getName()+" "+attribute.getValue());
    }
    //
    Iterator<Element> iterator2=book.elementIterator();
    while (iterator2.hasNext()) {
    Element element = (Element) iterator2.next();
    System.out.println(element.getName()+" "+element.getStringValue());
    }
    
    }
    } catch (DocumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
  • 相关阅读:
    滚动条滚动方向
    阶乘函数-尾递归
    返回顶部
    CommonJS
    vuessr
    随机字符串
    indexedDB
    深层次选择器
    Vue3.0简单替代Vuex
    shell 学习笔记
  • 原文地址:https://www.cnblogs.com/zhao307/p/5348198.html
Copyright © 2020-2023  润新知