Java的xml解析小工具

xml解析小工具(java)

对于java来解析xml文件在许许多多的工具之中都有涉及,比如hibernate就需要用户通过xml来建立表和java对象之间的映射关系,这确实很常用。我们常常把键值对用properties来处理,而有层次结构的往往可以使用xml来进行记录。
下面看一下jdk自带的api是如何解析xml的吧:
这是Student.xml文件在src目录下

<hzy>
    <student Sid="1" Isgood="yes">
        <property name="hzy"></property>
        <property age="15"></property>
        <property tail="185"></property>
    </student>
    <student Sid="2" Isgood="no">
        <property name="ya"></property>
        <property age="16"></property>
        <property tail="156"></property>
    </student>
</hzy>

这是传统的xml解析

package test;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;

public class XMLReader {
    public static void main(String[] args) {
        //获得xml文件的输入流
        InputStream is = XMLReader.class.getResourceAsStream("/student.xml");
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = null;
        Document document = null;
        //不变三连,document是xml的根节点抽象对象
        try {
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
            document = documentBuilder.parse(is);
            //根据输入流把根节点找出来
        } catch (ParserConfigurationException e) {
               e.printStackTrace();
        } catch (SAXException e) {
               e.printStackTrace();
        } catch (IOException e) {
               e.printStackTrace();
        }
        NodeList student = document.getElementsByTagName("student");
        //遍历根节点下的所有student子节点
        for(int i=0;i<student.getLength();i++) {
            Element element = (Element) student.item(i);
            String Sid = element.getAttribute("Sid");
            String Isgood = element.getAttribute("Isgood");
            System.out.println(Sid);
            System.out.println(Isgood);
            NodeList properties = element.getElementsByTagName("property");
            //遍历student节点下的所有property节点
            for(int j=0;j<properties.getLength();j++){
                Element pelement = (Element) properties.item(j);
                String name = pelement.getAttribute("name");
                String age = pelement.getAttribute("age");
                String tail = pelement.getAttribute("tail");
                System.out.println(name+" "+age+" "+tail);
            }
        }
    }
}

我们发现代码的重复性太高了,这还只是一个两层的xml,如果层次很多的话,是要遍历很多次的,就是会有许许多多的循环,这非常容易出错,令我们逻辑产生混乱。
java自然是要把硬性的,重复的代码打成工具,让以后更加简单的使用。
如何做,如下:
1.我们发现documentBuilder是不变的,所以用单例模式写一个就行啦!
2.每次循环是一样,但循环里头的是要在具体应用时才能确定的,这个时候给个抽象方法,让用户自己去实现才显得合理,当然也可以用接口。
3.xml文件名不一样,所以提供方法加载xml得到根节点就好啦!

package test;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;

public abstract class XMLReader {
    private static DocumentBuilder documentBuilder;
    //给documentBuilder单例一下
    private static void init(){
      if(documentBuilder==null) {
          try {
              documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          } catch (ParserConfigurationException e) {
              System.out.println("documentBuilder出错");
              e.printStackTrace();
          }
      }
    }
    //不管怎么抽取,总是要给一个获取Document的方法
    protected static Document getDocument(String xmlpath)  {
        init();
        InputStream is = XMLReader.class.getResourceAsStream(xmlpath);
          return getDocument(is);
    }
    //上边的重载,符合更多人的习惯
    protected  static Document getDocument(InputStream is) {
        init();
        try {
            return documentBuilder.parse(is);
        } catch (SAXException e) {
            System.out.println("xml文件打开出错,检查路径:");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("xml文件打开出错,检查路径:");
            e.printStackTrace();
        }
        return null;
    }
    //抽象方法,具体的实现交给用户吧
    protected abstract void dealReaderProperty(Element element,int item);
     //循环读取子节点并且调用抽象方法
    protected  XMLReader XMLReader(Document document,String tagName) {
        NodeList student = document.getElementsByTagName(tagName);
        for (int i = 0; i < student.getLength(); i++) {
            Element element = (Element) student.item(i);
            dealReaderProperty(element,i);
        }
        return this;
    }
    //和上面的一样根节点变成标记节点而已
    protected  XMLReader XMLReader(Element element,String tagName) {
        NodeList student = element.getElementsByTagName(tagName);
        for (int i = 0; i < student.getLength(); i++) {
            Element element1 = (Element) student.item(i);
            dealReaderProperty(element1,i);
        }
        return this;
    }
}

下面来一个测试!

   package test;

import org.w3c.dom.Element;


import javax.sql.rowset.WebRowSet;
import javax.sql.rowset.spi.XmlReader;
import java.io.InputStream;
import java.io.Reader;
import java.sql.SQLException;

public class Test {
    public static void main(String[] args) {
        InputStream is = Test.class.getResourceAsStream("/student.xml");
        new XMLReader() {
            @Override
            protected void dealReaderProperty(Element element, int item) {
                  String Sid = element.getAttribute("Sid");
                  String Isgood = element.getAttribute("Isgood");
                System.out.println(Sid+" "+Isgood);
                new XMLReader() {

                    @Override
                    protected void dealReaderProperty(Element element, int item) {
                        String name = element.getAttribute("name");
                        String age = element.getAttribute("age");
                        String tail= element.getAttribute("tail");
                        System.out.println(name+" "+age+" "+tail);
                    }
                }.XMLReader(element,"property");
            }
        }.XMLReader(XMLReader.getDocument(is),"student");
    }
}
这里小编说一下你自己写的抽象方法dealReaderProperty为啥被调用了,首先创建了匿名对象,调用了XMLReader方法,看我们的工具类,在XMLReader方法里头调用了dealReaderProperty方法。事实上就是一个实现了抽象类的新对象调用了XMLReader而已,然后就循环输出啦!,

这是输出情况

  1 yes
    hzy  
     15 
      185
    2 no
    ya  
     16 

没有问题呀!这一下子省了好多好多代码,我们只要给个Document根节点,自己写dealReaderProperty(Element element, int item)方法就可以完成读取啦。

猜你喜欢

转载自blog.csdn.net/h1311454244/article/details/82889919