• 解析xml,几种方式


      市面上解析xml分两种方式,1.dom  2.sax ,xml解析常见的一共有三种开发包,1.jaxp  2.jdom  3.dom4j,这三种方式最常用的是dom4j,jaxp和jdom很少有人用,jaxp是sun公司开发的,对于这个sun公司老是我就不知道怎么说他,被收购后我就没法叫,是叫甲骨文还叫原sun公司,别扭,书归正传,jaxp虽然使用起来很烂,但是它是标准,这个我们必须得懂,没准那天对jaxp二次开始开发,它就好用了,还是只得期待的,所以,首先我们来说下jaxp的用法,

      jaxp是开发包是j2SE的一部分,它由javax.xml, org.w3c.dom, org.xml.sax,还有其自包组成

      在javax.xml.parse包中定义了几个工厂类,程序员可以调用这些工厂类,得到xml的dom和sax解析器,从而实现对xml的解析。

      要用jaxp的dom解析xml需要按三步走,

        第一步:创建工厂

        第二步:拿到一个dom解析器

        第三步:得到Document对象

      看代码:

      

    1 //创建工厂
    2 DocumentBuilderFactory factor = DocumentBuilderFactory.newInstance();
    3 //得到dom解析器
    4 DocumentBuilder builder = factor.newDocumentBuilder();
    5 //得到Docuemnt
    6 Document document = builder.parse("src/student.xml");

      注意DocumentBuilderFactory是一个抽象方类,它向外界提供了一个得到实例的方法,通过工厂在得到dom解析器,dom解析器在加载一个xml让后返回一个文档对象,然后我们就能对文档进行读取了。

      得到了Document,然后写几个简单的查询,

      我们先读取一下xml文档的所有信息

     1 public void read1() throws Exception{
     2     //创建工厂
     3     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     4     //得到dom解析器
     5     DocumentBuilder builder = factory.newDocumentBuilder();
     6     //得到Document文档对象
     7     Document document = builder.parse("src/student.xml");
     8     Node node = document.getElementsByTagName("学校").item(0);//学校是xml的文档根节点
     9     list(node);//循环显示
    10 }
    11 private void list(Node node) {
    12                 //用于判断node是否为一个节点
    13     if(node instanceof Element){
    14            System.out.println(node.getNodeName());
    15     }
    16     NodeList childs = node.getChildNodes();
    17     for(int i = 0;i<childs.getLength();i++){
    18             list(childs.item(i));
    19     }
    20 }

      我们先获取一个节点的值,

     1 //创建工厂
     2 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     3 //得到一个dom解析器
     4 DocumentBuilder builder = factory.newDocumentBuilder();
     5 //得到一个Document对象
     6 Document document = builder.parse("src/student.xml");
     7 NodeList list = doc.getElementsByTagName("名字");
     8 //这里我只想得到第一个学生的名字
     9 Node node = list.item(0);
    10 System.out.println(node.getTextContent());

      获取一个节点的Attribute属性的值

     1     //创建dom工厂
     2     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     3     //得到dom解析器
     4     DocumentBuilder builder = factory.newDocumentBuilder();
     5     //得到doc文档
     6     Document doc = builder.parse("src/student.xml");
     7     //元素
     8     Element bookName = (Element) doc.getElementsByTagName("书名").item(0);
     9     String value = bookName.getAttribute("name");
    10     System.out.println(value);

      对于xml而言,查询无非就是差标签的值,和标签属性的值,如果大家想深学,想探究jaxp的话,去看帮助文档吧

      下面往xml里添加节点

      这里我写一个比较难的添加,就是给特定的位置添加节点,这个你会了,正常的添加你也就回了

     1         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     2         DocumentBuilder builder = factory.newDocumentBuilder();
     3         Document doc = builder.parse("src/book.xml");
     4         //创建一个新节点
     5         Element e = doc.createElement("售价");
     6         e.setTextContent("59.0");
     7         //得到一个参考节点
     8         Element refChild =(Element) doc.getElementsByTagName("价格").item(0);
     9         //得到要插入的节点
    10         Element element = (Element) doc.getElementsByTagName("书").item(0);
    11         //添加节点
    12         element.insertBefore(e, refChild);
    13         
    14         //把内存里的xml,写回到本地的xml文件
    15         TransformerFactory transformerFactory = TransformerFactory.newInstance();
    16         Transformer transformer = transformerFactory.newTransformer();
    17         transformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream("src/book.xml")));

      这里要注意,我们添加完了节点element.insertBefore(e, refChild);之后,没有后面的代码的话我们本地的xml不会增加,为什么呢,那我们加到哪去了。我们这个是添加到了内存里,内存里的xml肯定对了,所以我们要把内存里的xml写回到我们本地。这里用到一个类,就是Transform,这个类能帮助我把内存中的xml写回本地。

       添加一个属性

     

     1      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     2         DocumentBuilder builder = factory.newDocumentBuilder();
     3         Document doc = builder.parse("src/book.xml");
     4         
     5         Element e = (Element) doc.getElementsByTagName("书名").item(0);
     6         e.setAttribute("name", "添加的新属性");
     7         
     8         //把内存里的xml,写回到本地的xml文件
     9         TransformerFactory transformerFactory = TransformerFactory.newInstance();
    10         Transformer transformer = transformerFactory.newTransformer();
    11         transformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream("src/book.xml")));

      注意一定要从内存中,写回本地。

      删除,删除一定要用父节点来删子节点。

     1 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     2         DocumentBuilder builder =  factory.newDocumentBuilder();
     3         Document doc = builder.parse("src/book.xml");
     4         
     5         Element e = (Element) doc.getElementsByTagName("价格").item(0);
     6         e.getParentNode().removeChild(e);
     7         
     8         
     9         TransformerFactory transformerFactory = TransformerFactory.newInstance();
    10         Transformer transformer = transformerFactory.newTransformer();
    11         transformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream("src/book.xml")));

       以上是jaxp对xml的crud。

      下面说一下jaxp的sax解析器,对xml的解析,dom解析xml文档时,会把整个读取后的xml放在内存中,在内存中dom树代表Document,这样会有一个问题,如果xml比较大,就会消耗大量的内存,而且很容易造成内存溢出。对于sax解析的话,那么它允许你在读取的时候进行操作,不需要等整个文档加载完成。

      sax采用事件处理方式解析xml,一共两个部分 1.解析器   2.事件处理器

          解析器可以使用jaxp的api来创建,创建完成,就可以指定解析器去解析某个xml文档。这个解析器解析到xml文档的一个组成部分,都会调用一个事件处理器方法,解析器在调用事件处理器的时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器

      事件处理器由我们自己编写,我们通过事件处理器总方法的参数,就可以获取到sax解析xml的内容。

      一张图,让你更理解sax

      

      想要了解更过,去看ContentHandler 的api

      来看一个简单的sax解析,这个一共分5部

          1.创建工厂

          2.得到解析器

          3.得到读取器

          4.设置内容处理器

          5.读取xml文档内容

      看一段代码

     

        //1.创建工厂
            SAXParserFactory factory = SAXParserFactory.newInstance();
            
            //2.得到解析器
            SAXParser parser =  factory.newSAXParser();
            
            //3.得到读取器
            XMLReader reader = parser.getXMLReader();
            
           //4.设置内容处理器
                //这个内容处理器是我们自己写的,我们自己写的这个类要实现
            reader.setContentHandler(null);
            //5.读取xml文档内容
            reader.parse("src/book.xml");

      下面我们自己写一个处理器,四个处理器,我们对内容修改,那就要写一个内容处理器ContentHandler,这里实现ContentHandler,常用的方法有startElement(),endElement()

     characters()

     ContentHandler
     1 class ListXML implements ContentHandler{
     2     @Override
     3     public void startElement(String uri, String localName, String qName,
     4             Attributes atts) throws SAXException {
     5     }    
     6     @Override
     7     public void endElement(String uri, String localName, String qName)
     8             throws SAXException {
     9     }    
    10     @Override
    11     public void characters(char[] ch, int start, int length)
    12             throws SAXException {
    13     }
    14 
    15     @Override
    16     public void endDocument() throws SAXException {
    17         // TODO Auto-generated method stub
    18         
    19     }
    20 
    21 
    22 
    23     @Override
    24     public void endPrefixMapping(String prefix) throws SAXException {
    25         // TODO Auto-generated method stub
    26         
    27     }
    28 
    29     @Override
    30     public void ignorableWhitespace(char[] ch, int start, int length)
    31             throws SAXException {
    32         // TODO Auto-generated method stub
    33         
    34     }
    35 
    36     @Override
    37     public void processingInstruction(String target, String data)
    38             throws SAXException {
    39         // TODO Auto-generated method stub
    40         
    41     }
    42 
    43     @Override
    44     public void setDocumentLocator(Locator locator) {
    45         // TODO Auto-generated method stub
    46         
    47     }
    48 
    49     @Override
    50     public void skippedEntity(String name) throws SAXException {
    51         // TODO Auto-generated method stub
    52         
    53     }
    54 
    55     @Override
    56     public void startDocument() throws SAXException {
    57         // TODO Auto-generated method stub
    58         
    59     }
    60 
    61     
    62 
    63     @Override
    64     public void startPrefixMapping(String prefix, String uri)
    65             throws SAXException {
    66         // TODO Auto-generated method stub
    67         
    68     }
    69     
    70 }

      然后我们去查帮助文档,我们会看到一个DefaultHandler,原来人家都给我们写好了,这个我们就可以把多余的方法去掉,

      写一个完整的sax读取xml,这个读取xml全部内容,

     1 //1.创建工厂
     2         SAXParserFactory factory = SAXParserFactory.newInstance();
     3         
     4         //2.得到解析器
     5         SAXParser parser =  factory.newSAXParser();
     6         
     7         //3.得到读取器
     8         XMLReader reader = parser.getXMLReader();
     9         
    10         //4.设置内容处理器
    11         reader.setContentHandler(new GetXML());
    12         //5.读取xml文档内容
    13         reader.parse("src/book.xml");
    14 
    15 //下面是一个内容处理器
    16 class GetXML extends DefaultHandler{
    17     @Override
    18     public void startElement(String uri, String localName, String qName,
    19             Attributes attributes) throws SAXException {
    20         for(int i = 0 ; atts != null && i < atts.getLength(); i++){
    21             String attrName = atts.getQName(i);
    22             String attrVlaue = atts.getValue(i);
    23             System.out.println(attrName + "=" + attrVlaue);
    24         }
    25         System.out.println("<"+qName+">");    }
    26     
    27     @Override
    28     public void characters(char[] ch, int start, int length)
    29             throws SAXException {
    30         System.out.println(new String(ch,start,length));        
    31     }
    32 
    33     @Override
    34     public void endElement(String uri, String localName, String qName)
    35             throws SAXException {
    36          System.out.println("<"+qName+"/>");            }
    37 }

      

        我觉得sax解析能做到这样就行了。

      下面是dom4j,dom4j好用是公认的,曾经也有人做过实验,dom4j,最快,jdom第二,jaxp最慢,第二的就不用学了。

      我认为dom4j不用任何人交,不需要交,看文档就可以,提醒大家,看dom4j的xpath的时候找好地方,xpath的文档官方有中文,这一点就很爽,需要什么直接

    看文档,养成这个好习惯。

     推荐文章

    http://xhy0422.javaeye.com/blog/50235

       

       

      

    如果有使用请标明来源:http://www.cnblogs.com/duwenlei/
  • 相关阅读:
    python 容器的门道
    Python四种常用容器类型
    python容器类型的协议
    MySQL中的锁(表锁、行锁)
    mysql 的垂直分表和水平分表; 垂直分库和水平分库
    前端鉴权的兄弟们:cookie、session、token、jwt、单点登录
    基于多源异构数据的安全知识图谱的自动构建和应用
    数据库心得
    Hadoop
    [NOIP2015 提高组] 神奇的幻方
  • 原文地址:https://www.cnblogs.com/duwenlei/p/3482521.html
Copyright © 2020-2023  润新知