XML 四大解析模式区分(DOM解析、SAX解析、JDOM解析、DOM4J解析)

例子

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="1">
<name>亨利谁与争锋</name>
<author>天下足球</author>
<year>2011</year>
<price>89</price>
</book>
<book id="2">
<name>贝影</name>
<year>2008</year>
<price>77</price>
<language>English</language>
</book>
</bookstore>

DOM解析、SAX解析、JDOM解析、DOM4J解析


DOM解析

(1)创建工厂、机器、对象

       DocumentBuilderFactory dbf = new DocumentBuilderFactory();
         DocumentBuilder db =dbf.DocumentBuilder();
         Document document = db.parse("src/res/book.xml")

  (2)解析节点属性名、节点属性值

    ①对于book节点个数未知

        获取所有book节点的集合
          Nodelist booklist = document.getElementByTagName("book");
        使用for循环通过item()方法遍历每个book节点
          Node book = booklist.item(i);
        并获取book节点的所有属性集合
          NameNodeMap attrs = book.getAttribute();
        使用for循环通过item()方法遍历book的属性
          Node attr = attrs.item(j);
        获取属性名
          attr.getNodeName();
        获取属性值
          attr.getNodeValue();

    ②对于已经找到book节点只有一个ID属性可用以下方法,使用强制类型转换

          Element book = (Element) booklist.item(i);
          String attrValue = book.getAttribute("id");
         获取id属性的属性值:attrValue;

 (3)解析子节点名、子节点值

         Nodelist childNodes = book.getChildNodes();
        遍历childNodes获取每个节点的节点名和节点值,其中节点中包括空格和换行符
        使用for循环遍历
           区分text类型和element类型的node,通过getNodeType();
           childNodes.item(k).getNodeType() == Node.ELEMENT_NODE
           childNodes.item(k).getNodeName();
        获取子节点的节点值
           需要先获取book子节点,然后获得子节点的子节点的节点值
           chileNodes.ietm(k).getFirstChild().getNodeValue(); 
               

 (4).getNodeValue()与.getTextContent()的区别

       ChildNodes.item(i).getFirstChild().getNodeValue()与ChildNodes.item(i).getTextContent()的
       区别:子节点中还包含其他子节点时,后者可以把子节点的值都显示出来。
          getTextContent()获取节点中的text内容(即节点值).
          getNodeType().............有text,element,attr三个
       而Element如果要获取值,必须读取它的子节点,<name>content</name>认为content是namae的子节点;
       两种方法:
          getFirstChild().getNodeName();(获取子节点再获取值)
          getTextContent();(获取content方法)


SAX解析

    1.与DOM解析的差异

      (1)在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,
         从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致
         内存溢出。
      (2)SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。从xml文件
         的最上面开始逐一解析每一个节点,可以对于每一个节点做出其处理方式。
   

   2.SAX解析XML文档

       SAX解析XML文档的一般步骤:
    (1)创建SAX解析工厂、解析器对象、XML的读取器
         SAXParserFactory spf = SAXParserFactory.newInstance();       
         SAXParser sp = spf.newSAXParser();
         XMLReader xmlReader = sp.getXMLReader();

    (2)设置读取器的事件处理器、解析xml文件       
         xmlReader.setContentHandler(new BookParserHandler());  
         xmlReader.parse("src/res/book.xml");

    (3)创建ParserHandler的类
         并且重写startDocument、endDocument、startElement、endElement的方法
         startDocument:解析xml文件的标签开始
         endDocument:解析xml文件的标签开始
         startElement:解析xml文件开始
         endElement:解析xml文件开始
         characters:解析xml节点属性
         可以定义全局变量int bookindex = 0;为在main中设置解析每本书

     (4)解析xml文件的节点属性
         调用startElement(String url,String localName,String qName,Attributes attributes)方法;
         开始解析book元素的属性
         if(qName.equals("book")){
             //已知book元素下属性名称,根据属性名称获取属性值
             String value = attributes.getValue("id");
             //不知道book元素下属性名和个数,可以使用for循环遍历book下属性
             属性名:attributes.getQName(i);
             属性值:attributes.getValue(i);
             }
         判断解析book是否结束
         在endElement方法中使用
         if(qName.equals("book")){
               结束该本书的解析 
               }
     (5)解析xml文件的节点名和节点间文本
         解析文件的节点名,可以判断
           if(!qName.equals("book")&&!qName.equals("bookstore")){
            打印出}
         解析节点值,
         新建Characters方法
         public void characters(char[] ch, int start, int length){
               String value = new String(ch, start, length);
              if(!value.trim().equals("")){//去掉文本后的空格
                     value;//可以得到节点值
               }
            }
     (6)使用xml解析将xml的内容和结构存入Java对象
         新建book类,创建所有属性,并创建get和set方法
         并在解析book值时,将得到的属性值set进book的方法中。




JDOM解析

      1.导入jar包

     

    2.准备工作

    (1)创建一个SAXBuilder对象

      SAXBuilder saxBuilder = new SAXBuilder;

     (2)创建一个输入流,将xml文件加载到输入流

      InputStream in = new FileInputStream("src/res/books.xml");

     (3)通过saxBuilder的build方法,将输入流加载到saxBuilder

      Document document = saxBuilder.build(in);

     (4)通过document对象获取xml的根节点

      Element rootElement = document.getRootElement();

     (5)获取根节点下的子节点的List集合

      List<Element> bookList = rootElement.getChildren();

    3.解析节点属性

     (1)采用for循环遍历bookList中每个元素

         for(Element book : bookList){
                bookList.indexof(book);可以获取当前该本书处于bookList中的位置
          }  

     (2)解析book的属性

         List<Attribute> attrList = book.getAttributes();
         遍历attrList(针对不清楚book节点下属性的名字及数量)
         ——————————————————————————————————————————————
         book.getAttributeName("");
         book.getAttributeValue("属性名");
         用以上两种方法可以获取已知的节点属性名和属性值
         ——————————————————————————————————————————————
         for(Attribute attr : attrList){
            获取属性名
            String attrName = attr.getName();
            获取属性值
            String attrValue = attr.getValue();
          }

     (3)解析子节点名和子节点值

          List<Element> bookChilds = book.getChildren();
          遍历bookChilds 
          for (Element child : bookChilds ){
                 child.getName();
                 child.getValue();
          }

     4.解析时乱码的处理

        (1)encoding编解码方式更改

        (2)若(1)无法解决时

           在创建输入流时可以改为使用InputStreamReader( ,"UTF-8");
           通过使用字符流的方式

     5.JDOM中存储Book对象

        (1)创建book对象

           Book bookEntity = new Book();

        (2)判断id属性

           if(attrName.equals("id")){
             bookEntity.setId(attrValue)
            }

        (3)判断属性名

           if(child.getName().equals("name")){
             bookEntity.setName(child.getValue());
           }
           通过以上方法对每一个属性都进行判断

        (4)创建一个ArrayList来存储对象

           private static ArrayList<book> booksList = new ArrayList<book>();
           booksList.add(bookEntity);
           bookEntity = null;

     6.JDOM中jar包的引用

         若按之前的操作,有可能会发生由于工程的导入导出操作导致jar丢失,此时可以按一下操作解决。
         在package下new一个folder,然后将放在桌面的jar包复制进刚刚new的folder中去,然后在package中继续build path,然后选中刚刚复制的jar 包。 




DOM4J解析

 1.DOM4J解析节点

      解析books.xml文件

      (1)创建SAXReader的对象reader   

      SAXReader reader = new SAXReader();

      (2)通过reader对象的read方法加载book.xml文件,获取document对象

      Document document = reader.reader(new File("src/res/book.xml"));

      (3)通过document对象获取根节点bookstores

      Element bookStore = document.getRootElement();

      (4)通过element独享的elementIterator方法获取迭代器

      Iterator it = bookStore.elementIterator();

      (5)遍历迭代器,获取根节点中的信息(书籍)

      while(it.hasNext()){
         Element book = (Element)it.next();
         获取book的属性名和属性值
         List<Attribute>bookAttrs = book.attribute();
         遍历每本书中的所有节点
         for (Attribute attr : bookAttrs){
             获取属性名
             attr.getName(); 
             获取属性值
             attr.getValue();
            }
         }

    2.DOM4J解析子节点信息

       遍历book子节点依然可以使用elementIterator方法获取迭代器
       Iterator itt = book.elementIterator(); 
       while(itt.hasNext()){
          Element bookChild = (Element)itt.next();
             获取节点名
             bookChild.getName(); 
             获取节点值
             bookChild.getStringValue();      
      }


    3.XPath

导包:javaxen.jar

Xpath是一个规范,
    我们在使用基本用法的时候,都是基于查询的。

    XPath的语法

                 /开头,表示绝对路径
                //开头:表示满足// 之后的所有元素
                *:表示选择所有由 * 之前的路径所定位的元素 /*/*/*/BBB :表示在第三级目录下的BBB,不会找第四级目录下的BBB
                /AAA/BBB[1]:表示选择此目录下的第一个BBB
                /AAA[@id]:表示选择包含 id属性 的AAA
    //找第一本书的作者
    root.selectSingleNode("/书架/书/作者[1]");可能会变红,但是可以运行


实例:

<root>
    <success>1</success>
    <result>
        <item_0>
        <days>2018-05-19</days>
        <week>星期六</week>
        <citynm>北京</citynm>
        <temperature>28℃/16℃</temperature>
        <humidity>0%/0%</humidity>
        <weather>多云转阴</weather>
        <wind>西风</wind>
        <winp>&lt;3级</winp>
        <temp_high>28</temp_high>
        <temp_low>16</temp_low>
        <humi_high>0</humi_high>
        <humi_low>0</humi_low>
    </item_0>
        <item_1>
            <days>2018-05-20</days>
            <week>星期日</week>
            <citynm>北京</citynm>
            <temperature>21℃/16℃</temperature>
            <humidity>0%/0%</humidity>
            <weather>阴转小雨</weather>
            <wind>东风转东南风</wind>
            <winp>&lt;3级</winp>
            <temp_high>21</temp_high>
            <temp_low>16</temp_low>
            <humi_high>0</humi_high>
            <humi_low>0</humi_low>
        </item_1>
   </result>
</root>
创建一个天气类:weather

然后测试:
public class weatherTest {

    public static void main(String[] args) throws DocumentException {

        ArrayList<weather> weathers = new ArrayList<>();
        //创建SAXReader的对象reader
        SAXReader reader = new SAXReader();

        //通过reader对象的read方法加载book.xml文件,获取document对象
        Document document = null;

            document = reader.read("weather.xml");
            Element rootElement = document.getRootElement();

            for (int i = 0; i <2 ; i++) {
                weather weather11 = new weather();
                String item = "item_" + i;

                Element elem1 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/days");
                weather11.setDate(elem1.getText());

                Element elem2 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/week");
                weather11.setWeek(elem2.getText());

                Element elem3 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/citynm");
                weather11.setCitynm(elem3.getText());

                Element elem4 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/temperature");
                weather11.setTemperature(elem4.getText());

                Element elem5 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/weather");
                weather11.setWeather(elem5.getText());

                Element elem6 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/wind");
                weather11.setWind(elem6.getText());

                Element elem7 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/winp");
                weather11.setWinp(elem7.getText());

                Element elem8 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/temp_high");
                weather11.setTemp_high(elem8.getText());

                Element elem9 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/temp_low");
                weather11.setTemp_low(elem9.getText());

                Element elem10 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/humi_high");
                weather11.setHumi_high(elem10.getText());

                Element elem11 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/humi_low");
                weather11.setHumi_low(elem11.getText());

                //添加到weathers中
                weathers.add(weather11);
            }
        //输出weather
        for (weather wea : weathers) {
            System.out.println(wea);
        }

    }
}




几种解析方法pk

   1.分类

      基础解析方式:DOM、SAX
      扩展解析方式:JDOM、DOM4J

    2.DOM解析过程:

      一次性将整个xml文件加载到内存中,形成DOM树
      优点:形成了树结构,直观好理解,代码更容易编写解析过程中树结构保留在内存中,方便修改
      缺点:当xml文件较大时,对内存消耗比较大,容易影响解析性能并造成内存溢出

   3.SAX解析过程:

      逐条语句判断解析(基于时间的解析方式)
      优点:采用事件驱动模式,对内存消耗比较小适用于只需要处理xml中数据时
      缺点:不易编码,很难同时访问同一个xml中的多处不同数据

    4.JDOM解析过程:

      仅使用具体类而不使用接口
      API大量使用了Collections类
      

    5.DOM4J解析过程:

      JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能
      DOM4J使用接口和抽象基本类方法,一个优秀的Java XML API具有性能优异、灵活性好、功能强大和极端易使用的特点,
      是一个开放源代码的软件













猜你喜欢

转载自blog.csdn.net/qq_38962004/article/details/80379031