zoukankan      html  css  js  c++  java
  • jaxp使用笔记

    XML文件的解析技术有DOM和SAX方式,在Android中还有pull解析方式,这里不再讨论

    DOM解析的方式和js中的DOM操作是一致的,DOM解析一次将文档加载入内存建立树型模型,但是如果XML文档过大,会出现内存溢出的问题,DOM也有优点:方便进行增删改操作

    SAX解析方式是根据事件驱动一行一行进行加载解析的,所以不会出现内存溢出的问题,而且方便查询,但是它有个缺点:不能进行增删改操作

    目前XML的解析器有:

    1. sun开发的jaxp(本次记录的)
    2. dom4j (最为常用)
    3. jdom (使用较少)

    注意:这里说的是解析器,解析器是根据解析技术开发的工具,解析技术记住DOM和SAX即可

    因为jaxp是sun公司开发的,直接存在于JDK中,所以还是有必要学习一下

    jaxp进行DOM解析

    使用jaxp进行DOM解析可以分为四步:

    第一步 创建解析器工厂 

    DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();

    第二步 根据工厂创建解析器

    DocumentBuilder builder = factory.newDocumentBuilder();

    第三步 使用解析器解析XML文件,得到Document对象

    Document document = builder.parse("XML文件");

    第四步 根据jaxp的API对Document对象进行操作

    例如  getElementsByTagName(标签名)获得节点集合     NodeList类的getLength()方法获得节点个数    

    NodeList类的item(int)方法获得某个节点    Node类的getTextContent()方法获得节点的文本值 等等

    person.xml文件:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <person> <student> <name>lz</name> <age>21</age> </student> <student> <name>zhanshang</name> <age>21</age> </student> </person>

    先来看一个简单解析XML文件的例子(从name节点集合中获得每个name节点的文本值):

        /**
         * 使用jaxp的DOM解析方法解析XML
         * @throws Exception 
         */
        @Test
        public void fun1() throws Exception{
            //1.创建工厂
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            //2.根据工厂创建解析器
            DocumentBuilder builder = factory.newDocumentBuilder();
            //3.解析XML得到Document对象
            Document document = builder.parse("src/person.xml");
            //4.根据Document对象得到元素集合
            NodeList nodeList = document.getElementsByTagName("name");
            //5.遍历节点集合,得到节点的值  使用item()方法根据下标获得节点
            for (int i = 0; i < nodeList.getLength(); i++) {
                String value=nodeList.item(i).getTextContent();
                System.out.println(value);
            }
        }

    注意:其中的Document和NodeList,Node等类都是org.w3c.dom包下的,不要导错

    结果输出:

    lz
    zhanshang

    添加节点

    添加节点使用的是appChild()方法,和js中DOM操作的添加节点方法名是一样的,添加节点操作中第四步需要说明一下:我们需要创建节点(创建元素节点createElement()方法,创建文本节点 createTextNode()方法),然后把节点添加到父节点下,其实逻辑和js中DOM一致,然后我们需要回写到XML文件中,因为我们之前的操作都是在内存中,需要回写到XML文件

    /**
         * 添加节点
         * @throws Exception
         */
        @Test
        public void fun2() throws Exception{
            //1.创建解析器工厂
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            //2.根据工厂创建解析器
            DocumentBuilder builder = factory.newDocumentBuilder();
            //3.解析XML,得到Document
            Document document = builder.parse("src/person.xml");
            //得到第一个student结点,并添加结点(内存中)
            Node student = document.getElementsByTagName("student").item(0);
            Element sex = document.createElement("sex");
            Text nan = document.createTextNode("男");
            sex.appendChild(nan);
            student.appendChild(sex);
            //4.回写数据到XML文件中
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
        }

    注意:使用javax.xml.transform包下的Transformer类回写,这个类也是先创建工厂,然后根据工厂创建Transformer类,最后使用这个类的transform()方法。使用jaxp添加节点会使XML文件的格式变乱,因为添加节点之后不会格式化,使用dom4j就可以格式化XML文件

    person.xml文件变为:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
        <student>
            <name>lz</name>
            <age>21</age>
                <sex></sex>
           </student>
        <student>
            <name>zhanshang</name>
            <age>21</age>
        </student>
    </person>

    修改操作

    修改文本节点的值使用的是Node类的setTextContent()方法,和getTextContent()方法相对

        /**
         * 修改节点
         * @throws Exception 
         */
        @Test
        public void fun3() throws Exception{
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse("src/person.xml");
            Node sex = document.getElementsByTagName("sex").item(0);
            sex.setTextContent("nan");
            //回写XML
            TransformerFactory transformerFactory=TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
        }

    person.xml文件变为:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
        <student>
            <name>lz</name>
            <age>21</age>
            <sex>nan</sex>
    </
    student> <student> <name>zhanshang</name> <age>21</age> </student> </person>

    删除节点

    接下来我们就把sex这个节点给删除吧,使用的方法是Node类的removeChild(),注意:使用1添加和删除都是相对于操作的节点的父节点来说的,所以需要先找到其父节点

        /**
         * 删除节点
         * @throws Exception 
         */
        @Test
        public void fun4() throws Exception{
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse("src/person.xml");
            Node student1 = document.getElementsByTagName("student").item(0);
            Node sex1 = document.getElementsByTagName("sex").item(0);
            student1.removeChild(sex1);
            //回写XML
            TransformerFactory transformerFactory=TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
        }

    person.xml文件又变回:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
        <student>
            <name>lz</name>
            <age>21</age>
        </student>
        <student>
            <name>zhanshang</name>
            <age>21</age>
        </student>
    </person>

    注意:DOM的增删改操作都需要在最后回写到XML文件中,不然只是在内存中操作

    遍历节点

    我是想把所有的元素节点遍历出来,遍历节点使用的是Node类的getChildNodes()方法,但是这个方法遍历只可以遍历一层层级关系,所以需要递归调用

        /**
         * 遍历节点
         * @throws Exception 
         */
        @Test
        public void fun5() throws Exception{
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse("src/person.xml");
            list1(document);
        }
        
        private void list1(Node node){      //遍历节点 Node类是Document类的父类
            if(node.getNodeType()==Node.ELEMENT_NODE){    //判断是否为元素节点  ELEMEN_NODE静态常量量 还有其他的静态常量表示其他类型的节点
                System.out.println(node.getNodeName());
            }
            NodeList nodeList = node.getChildNodes();
            for(int i=0;i<nodeList.getLength();i++){
                list1(nodeList.item(i));      //递归调用
            }
        }

    注意:list1()方法中有一个判断,判断该节点类型是否为元素节点,如果为元素节点才输出,如果不判断遍历之后会把空格,换行都当成文本节点输出,js的DOM操作中也有该问题

    结果输出为 :

    person
    student
    name
    age
    student
    name
    age

    jaxp进行SAX解析

    因为SAX解析不可以进行增删改操作,所以都是查询操作

    步骤分为四步(大致上与DOM解析的步骤一致,只是使用的是继承DefaultHandler的类进行处理解析结果):

    第一步 得到解析器工厂

    SAXParserFactory factory=SAXParserFactory.newInstance();

    第二步 根据工厂得到解析器

    SAXParser parser = factory.newSAXParser();

    第三步 解析XML文件,使用继承于DefaultHandler的类进行处理

    parser.parse("src/person.xml", new MyHandler1());

    MyHandler类继承DefaultHandler类,这个父类,最主要的方法是 : 

    startElement() 处理开始标签, 

    endElement() 处理结束标签, 

    characters() 处理文本

    前两者都有一个String类型的变量表示该标签名

    获得所有的标签

        /**
         * 获取所有标签
         * 
         */
        @Test
        public void fun1() throws Exception{
            //1.得到解析器工厂
            SAXParserFactory factory=SAXParserFactory.newInstance();
            //2.根据工厂创建解析器
            SAXParser parser = factory.newSAXParser();
            //3.解析XML文件
            parser.parse("src/person.xml", new MyHandler1());
        }
    
    
    class MyHandler1 extends DefaultHandler{
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            System.out.print("<"+qName+">");       //这里没有使用println,因为解析XML会把空格和换行都解析出来
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            System.out.print("</"+qName+">");
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            System.out.print(new String(ch,start,length));
        }
        
    }

    结果输出为:

    <person> 
      <student> 
        <name>lz</name>  
        <age>21</age> 
      </student>  
      <student> 
        <name>zhanshang</name>  
        <age>20</age> 
      </student> 
    </person>

    获得标签的值

    /**
         * 获得所有name标签的值
         */
        @Test
        public void fun2()throws Exception{
            SAXParserFactory factory=SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            parser.parse("src/person.xml", new MyHandler2());
        }
    
    
    
    class MyHandler2 extends DefaultHandler{
        
        private boolean flag=false;   //设置一个标志位,解析到name标签时改变标志位
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if(qName.equals("name")){
                flag=true;
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if(qName.equals("name")){
                flag=false;
            }
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if(flag==true){
                System.out.println(new String(ch,start,length));
            }
        }
        
    }

    结果输出为:

    lz
    zhanshang

    得到某一个标签的值

    /**
         * 获得第二个name标签的值
         */
        @Test
        public void fun3()throws Exception{
            SAXParserFactory factory=SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            parser.parse("src/person.xml", new MyHandler3());
        }
    
    
    
    class MyHandler3 extends DefaultHandler{
        
        private boolean flag=false;
        
        private int index=1;
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if(qName.equals("name")){
                flag=true;
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if(qName.equals("name")){
                flag=false;
                index++;
            }
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if(flag==true&&index==2){
                System.out.println(new String(ch,start,length));
            }
        }
        
    }

    结果输出为:

    zhanshang
  • 相关阅读:
    为TextBox定义快捷键
    (转)再谈“我是怎么招聘程序员的”
    (转)jQuery框架学习第二天:jQuery中万能的选择器
    (转)MongoDB学习笔记(一) MongoDB介绍及安装
    asp.net 导出CSV
    领域驱动设计下系统层次结构风格(转载)
    (转)谈谈数据加密的处理提供各种算法处理
    (转)REST服务开发实战
    领域驱动设计系列文章(2)——浅析VO、DTO、DO、PO的概念、区别和用处
    (转)你的工作不是命令人们去做什么
  • 原文地址:https://www.cnblogs.com/lz2017/p/7118171.html
Copyright © 2011-2022 走看看