原生JDK操作XML(不依赖框架)

182 阅读3分钟

约定:本文实践的JDK版本在8以上

原生JDK读取XML内容

总体步骤

  1. 创建DocumentBuilderFactory并配置,这是一个工厂对象
  2. 创建DocumentBuilder并配置,这是一个Document的建造者对象
  3. 使用DocumentBuilder获取Document对象。这个Document就代表了XML文档本身
  4. 使用Document提供的API可以获取xml节点,xml节点中的属性,xml节点中的子节点,xml节点中的文本等。

实战演示

完整代码在文章最底部

  1. 准备xml文件
<root>
    <book verison="2.0" year="2002">
        <name>三体</name>
        <author>刘慈欣</author>
    </book>
    <book version="1.0">
        <name>我不是潘金莲</name>
        <author>刘震云</author>
    </book>
</root>
  1. 按照上节介绍的步骤操作,第1步构建DocumentBuilderFactory对象并配置
// 使用静态方法创建工厂对象
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
// 设置对象的配置
documentBuilderFactory.setValidating(false);
documentBuilderFactory.setCoalescing(true); // 转义CDATA
documentBuilderFactory.setIgnoringElementContentWhitespace(true);
  1. 第2步构建DocumentBuilder对象并配置;需要用到上一步的工厂来生成该对象。其实也没啥配置,就是设置了下错误处理对象。
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    documentBuilder.setErrorHandler(new ErrorHandler() {
        @Override
        public void warning(SAXParseException exception) throws SAXException {
            System.out.println("warn" + exception.getMessage());
        }

        @Override
        public void error(SAXParseException exception) throws SAXException {
            System.out.println("error" + exception.getMessage());
        }

        @Override
        public void fatalError(SAXParseException exception) throws SAXException {
            System.out.println("fatalError" + exception.getMessage());
        }
});
  1. 第3步创建Document对象,使用上一步生成的builder对象解析指定xml文件生成该对象
Document document = documentBuilder.parse("D:/05_project/mybatis-code/src/main/java/org/apache/ibatis/amy/ixml/test.xml");
  1. 现在有了Document对象,就相当于有了一份XML文档,可以通过API获取到文档中的任何内容
  • xml的根节点 Document#getDocumentElement方法
  • xml的其他节点 Document#getDocumentElement方法
  • xml指定名称的节点 Document#getElementsByTagName方法
  • 节点中的属性 Node#getAttributes方法
  • 节点的标签名称 Node#getNodeName方法
  • 节点子节点 Node#getChildNodes方法
  • 节点的文本内容 Node#getTextContent方法
for (int i = 0; i < childNodes.getLength(); i++) {
    Node item = childNodes.item(i);
    String nodeName = item.getNodeName();
    if (!"book".equals(nodeName)) {
        continue;
    }
    System.out.println("-------------");
    String textContent = item.getTextContent();
    String nodeValue = item.getNodeValue();
    NamedNodeMap attributes = item.getAttributes();
    Optional.ofNullable(attributes).ifPresent(namedNodeMap -> {
        for (int j = 0; j < attributes.getLength(); j++) {
            Node attribute = attributes.item(j);
            System.out.println("attributes [" + attribute.getNodeName() + "]: " + attribute.getNodeValue());
        }
    });
    System.out.println("nodeName:" + nodeName);
    System.out.println("nodeValue:" + nodeValue);
    System.out.println("textContent:" + textContent);
    System.out.println();
}

输出:

-------------
attributes [verison]: 2.0
attributes [year]: 2002
nodeName:book
nodeValue:null
textContent:
        三体
        刘慈欣
    

-------------
attributes [version]: 1.0
nodeName:book
nodeValue:null
textContent:
        我不是潘金莲
        刘震云
Process finished with exit code 0

原生JDK写XML文件

起始很多框架已经实现该功能,而且jdk原生写基本用不上,这里就简单举个例子。

public void testWriteXml() throws Exception {
    String xmlString = """
                <root>
                    <book attr1="val1"></book>
                </root>
            """;
    //创建一个DocumentBuilderFactory的对象
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

    //创建DocumentBuilder对象
    DocumentBuilder db = dbf.newDocumentBuilder();
    //通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下
    Document document = db.parse(new StringBufferInputStream(xmlString));

    //获取所有book节点的集合
    NodeList bookList = document.getElementsByTagName("book");
    if (bookList == null || bookList.getLength() == 0) return;
    Node bookNode = bookList.item(0);
    Map<String,String> bookOptions = new HashMap<>();
    bookOptions.put("three body","三体");
    bookOptions.put("a","三体2");
    bookOptions.put("b","三体3");

    //加入节点、属性等操作
    for (Map.Entry<String, String> entry : bookOptions.entrySet()) {
        Element optionNode = document.createElement("option");
        optionNode.setTextContent(entry.getValue());
        optionNode.setAttribute("name", entry.getKey());
        bookNode.appendChild(optionNode);
    }
    //dom 转String
    DOMSource source = new DOMSource(document);
    StringWriter writer = new StringWriter();
    Result result = new StreamResult(writer);
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.transform(source, result);
    // 写入文档省略...(只需要把字符串利用IO流写入文档即可)
    System.out.println("生成的XML文档内容是\n" + writer.toString());
}

运行输出:

生成的XML文档内容是
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
    <book attr1="val1"><option name="a">三体2</option><option name="b">三体3</option><option name="three body">三体</option></book>
</root>

实战演示完整代码,XML文件内容在上文已经描述不再赘述。

public void testWriteXml() throws Exception {
        String xmlString = """
                    <root>
                        <book attr1="val1"></book>
                    </root>
                """;
        //创建一个DocumentBuilderFactory的对象
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        //创建DocumentBuilder对象
        DocumentBuilder db = dbf.newDocumentBuilder();
        //通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下
        Document document = db.parse(new StringBufferInputStream(xmlString));

        //获取所有book节点的集合
        NodeList bookList = document.getElementsByTagName("book");
        if (bookList == null || bookList.getLength() == 0) return;
        Node bookNode = bookList.item(0);
        Map<String,String> bookOptions = new HashMap<>();
        bookOptions.put("three body","三体");
        bookOptions.put("a","三体2");
        bookOptions.put("b","三体3");

        //加入节点、属性等操作
        for (Map.Entry<String, String> entry : bookOptions.entrySet()) {
            Element optionNode = document.createElement("option");
            optionNode.setTextContent(entry.getValue());
            optionNode.setAttribute("name", entry.getKey());
            bookNode.appendChild(optionNode);
        }
        //dom 转String
        DOMSource source = new DOMSource(document);
        StringWriter writer = new StringWriter();
        Result result = new StreamResult(writer);
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.transform(source, result);
        // 写入文档省略...(只需要把字符串利用IO流写入文档即可)
        System.out.println("生成的XML文档内容是\n" + writer.toString());
    }