Java验证解析XML

上一篇讲了Java解析XML,然而如果仅仅按照这种方法来操作,会发现需要大量冗长的编程和错误检查工作。不但需要处理元素间的空白字符,还要检查该文档包含的节点是否和你预期一样。所以在解析XML之前需要验证XML文档的正确性。

场景

例如,读入下面这个XML文档,请看Java XML文档解析


  
      
        Java 核心技术  
        Cornell   
        2014  
        89  
      
      
        深入浅出MyBatis  
        杨开振  
        2016  
        69  
      
      
        Java RESTful Web Service实战  
        韩陆  
        2016  
        59
      

如果不进行XML验证,会出现如下情况

  • 解析的时候需要判断两个节点中的空白字符,如果是空白字符就不读取,不是就读取。
  • 同时如果多写了一个属性computer到book节点。如果没有验证,那么解析的时候就会将category作为一个节点读入,这可能会导致错误。
      
        Java RESTful Web Service实战  
        韩陆  
        2016  
        59
        computer
      
  • 如果没对book id进行限制,那么可能存在两个book id相等,这个是不允许发生的

XML解析器

XML解析器最大好处就是它能自动检验某个文档是否具有正确的结构。可以提供文档类型定义(DTD)或一个XML Schema定义。DTD包含用于解释文档如何构成的规则,这些规则指定每个元素的合法子元素和属性。

DTD

-book.dtd 用来描述上述XML的构成的规则,DTD语法规则,参考链接
















将上述book.dtd纳入入到xml文件中。



  
      
        Java 核心技术  
        Cornell   
        2014  
        89  
      
      
        深入浅出MyBatis  
        杨开振  
        2016  
        69  
      
      
        Java RESTful Web Service实战  
        韩陆  
        2016  
        59
      

在DOM解析时候可以通过下列代码来进行验证

    dBuilderFactory = DocumentBuilderFactory.newInstance();
    //解析的时候开启验证
    dBuilderFactory.setValidating(true);
    //忽略节点之间的空白字符
    dBuilderFactory.setIgnoringElementContentWhitespace(true);
    dBuilder = dBuilderFactory.newDocumentBuilder();

整体代码如下

public class ReadXMLByDOMWithValidating {
    private static DocumentBuilderFactory dBuilderFactory = null;
    private static DocumentBuilder dBuilder = null;
    static {
        try {
            /**
             * 要读入一个XML文档,首先要有一个DocumentBuilder对象 可以从DocumentBuilderFactory中得到这个对象
             */
            dBuilderFactory = DocumentBuilderFactory.newInstance();
            dBuilderFactory.setValidating(true);
            dBuilderFactory.setIgnoringElementContentWhitespace(true);
            dBuilder = dBuilderFactory.newDocumentBuilder();
            dBuilder.setErrorHandler(new ErrorHandler() {

                public void warning(SAXParseException exception) throws SAXException {
                    throw exception;

                }

                public void fatalError(SAXParseException exception) throws SAXException {
                    // TODO Auto-generated method stub
                    throw exception;

                }

                public void error(SAXParseException exception) throws SAXException {
                    // TODO Auto-generated method stub
                    throw exception;
                }
            });
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static List listBooks(String filename) throws SAXException, IOException {
        List books = new ArrayList();
        // 可通过DocumentBuilder对象的parse()方法读入整个文档
        Document document = dBuilder.parse(filename);
        // 获得根节点,books.xml对应的就是bookstore节点
        Element root = document.getDocumentElement();
        // 输出根节点的名字,bookstore
        System.out.println(root.getTagName());
        // 获得所有的book节点
        NodeList children = root.getChildNodes();
        // 循环遍历各个book节点
        for (int i = 0; i < children.getLength(); i++) {
            // 获得第i个book节点
            Node child = children.item(i);
            // 用来存储第i个节点的内容
            List bookAttrbuteContent = new ArrayList();
            Book book = new Book();
            /**
             * 这里要注意的是dom会把两个节点之间的空白字符也当做节点 要判断是否是子元素, 而不是空白字符,这个可以参照 《Java核心技术卷
             * 二》的解析XML文档章节,有详细的解释
             */
            Element childElement = (Element) child;
            int bookId = Integer.parseInt(childElement.getAttribute("id").replace("book", ""));
            System.out.println(bookId);
            book.setId(bookId);
            NodeList bookAttrbuteList = childElement.getChildNodes();
            // 循环遍历book节点的各个子节点,如name,author...
            for (int j = 0; j < bookAttrbuteList.getLength(); j++) {
                Node bookAttrbute = bookAttrbuteList.item(j);
                String content = bookAttrbute.getTextContent().trim();
                System.out.println(((Element) bookAttrbute).getTagName() + ":" + content);
                bookAttrbuteContent.add(content);
            }
            book.setName(bookAttrbuteContent.get(0));
            book.setAuthor(bookAttrbuteContent.get(1));
            book.setYear(Integer.parseInt(bookAttrbuteContent.get(2)));
            book.setPrice(Integer.parseInt(bookAttrbuteContent.get(3)));
            books.add(book);
        }
        return books;
    }

    public static void main(String args[]) {
        String fileName = "./src/main/java/com/gethin/xmlparser/bookstore.xml";
        try {
            List books = ReadXMLByDOMWithValidating.listBooks(fileName);
            for (Book book : books) {
                System.out.println(book);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

源代码的github链接

你可能感兴趣的:(Java验证解析XML)