java中操作xml的方法总结

一丶常用方法

  主要有3个方面, 1读取xml文件, 2使用xpath根据指定路径获取某一节点数据 3, xml和java bean的转换

XmlUtils.java

/**
 * 和cn.hutool.core.util.XmlUtil许多功能重合, 本类可以当做学习的例子
 * 可以直接使用cn.hutool.core.util.XmlUtil
 *
 * @author TimFruit
 * @date 19-11-2 下午5:22
 */
public class XmlUtils {

    // --------------------------------------
    public static Document createXml(){
        return XmlUtil.createXml();
    }


    // --------------------------------------


    /**
     * 读取xml文档
     * @param xmlInputStream
     * @return
     */
    public static Document readXml(InputStream xmlInputStream){
        return readXml(xmlInputStream, false);
    }


    public static Document readXml(InputStream xmlInputStream, boolean validate){  // 参考mybatis parsing模块
        try {
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            factory.setValidating(validate);

            factory.setNamespaceAware(false);
            factory.setIgnoringComments(true);
            factory.setIgnoringElementContentWhitespace(false);
            factory.setCoalescing(false);
            factory.setExpandEntityReferences(true);

            DocumentBuilder builder=factory.newDocumentBuilder();
            return builder.parse(xmlInputStream);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (SAXException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    public static Document readXml(String xmlStr){
        return XmlUtil.parseXml(xmlStr); //使用hutool
    }




    // --------------------------------------

    // 根据路径获取某一节点

    public static XPath newXpath(){
        return XPathFactory.newInstance().newXPath();
    }

    /**
     * 根据路径获取某一节点, 语法看 https://www.w3school.com.cn/xpath/xpath_syntax.asp
     * @param expression
     * @param root  可以是document, 可以是Node等其他节点
     * @param xpath
     * @return 返回的节点可以修改
     */
    public static Node evalNode(String expression, Object root, XPath xpath){
        return (Node)evaluate(expression, root, XPathConstants.NODE, xpath);
    }


    public static NodeList evalNodeList(String expression, Object root, XPath xpath){
        return (NodeList)evaluate(expression, root, XPathConstants.NODESET, xpath);
    }

    public static Double evalDouble(String expression, Object root, XPath xpath) {
        return (Double) evaluate(expression, root, XPathConstants.NUMBER, xpath);
    }


    public static Boolean evalBoolean(String expression, Object root, XPath xpath) {
        return (Boolean) evaluate(expression, root, XPathConstants.BOOLEAN, xpath);
    }


    public static String evalString(String expression, Object root, XPath xpath) {
        return (String) evaluate(expression, root, XPathConstants.STRING, xpath);
    }


    public static Long evalLong(String expression, Object root, XPath xpath){
        return Long.valueOf(evalString(expression, root, xpath));
    }


    public static Integer evalInteger(String expression, Object root, XPath xpath){
        return Integer.valueOf(evalString(expression, root, xpath));
    }

    public static Float evalFloat(String expression, Object root, XPath xpath){
        return Float.valueOf(evalString(expression, root, xpath));
    }

    public static Short evalShort(String expression, Object root, XPath xpath){
        return Short.valueOf(evalString(expression, root, xpath));
    }


    private static Object evaluate(String expression, Object root, QName returnType, XPath xpath) {
        try {
            return xpath.evaluate(expression, root, returnType);
        } catch (Exception e) {
            throw new RuntimeException("Error evaluating XPath.  Cause: " + e, e);
        }
    }




    // --------------------------------------
    // 转成string

    public static String toStr(Node node){
        return toStr(node, false);
    }


    public static String toStr(Node node, boolean isPretty){
        return toStr(node, "utf-8", isPretty);
    }


    /**
     *
     * @param node
     * @param charset 编码
     * @param isPretty 是否格式化输出
     * @return
     */
    public static String toStr(Node node, String charset, boolean isPretty){
        final StringWriter writer = StrUtil.getWriter();
        final int INDENT_DEFAULT=2;
        try {
            XmlUtil.transform(new DOMSource(node), new StreamResult(writer), charset, isPretty ? INDENT_DEFAULT : 0);
        } catch (Exception e) {
            throw new UtilException(e, "Trans xml document to string error!");
        }
        return writer.toString();
    }



    //----------------------------------------
    // 和java bean转换

    public static JSONObject toJSONObject(String xmlStr){
        return XML.toJSONObject(xmlStr);
    }

    public static JSONObject toJSONObject(Node node){
        String xmlStr=toStr(node);
        return toJSONObject(xmlStr);
    }


    public static <T> T toBean(Node node, Class<T> clazz){
        return toJSONObject(node).toBean(clazz);
    }


    public static Node toNode(Object obj){
        String xml=toXml(obj);
        Node rootNode=readXml(xml).getFirstChild();
        return rootNode;
    }


    public static String toXml(Object obj){
        return XML.toXml(obj);
    }


}

 

 

二丶测试

@Test
    public void readXmlFromInputStreamTest(){
        BufferedInputStream bis=FileUtil.getInputStream("xml/bookstore.xml");

        Document document=XmlUtils.readXml(bis);


        String nodeName=document.getFirstChild().getNodeName();
        System.out.println(nodeName);
        Assert.assertTrue(nodeName.equals("bookstore"));

    }


    @Test
    public void readXmlStringTest() throws IOException {
        BufferedInputStream bis=FileUtil.getInputStream("xml/bookstore.xml");
        String xmlStr=StreamUtils.copyToString(bis, Charset.defaultCharset());
        Document document=XmlUtils.readXml(xmlStr);


        String nodeName=document.getFirstChild().getNodeName();
        System.out.println(nodeName);
        Assert.assertTrue(nodeName.equals("bookstore"));

    }



    // -------------------------------------------- xpath


    /*
    https://www.w3school.com.cn/xpath/xpath_syntax.asp


    nodename     选取此节点的所有子节点。
    /     从根节点选取。
    //     从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
    .     选取当前节点。
    ..     选取当前节点的父节点。
    @     选取属性。
     */
    @Test
    public void evalNodeTest(){
        BufferedInputStream bis=FileUtil.getInputStream("xml/bookstore.xml");
        Document document=XmlUtils.readXml(bis);
        XPath xpath=XmlUtils.newXpath();


        // 1. 使用xpath表达式读取根节点
        Node rootNode=XmlUtils.evalNode("/bookstore", document, xpath);
        Assert.assertEquals("bookstore", rootNode.getNodeName());


        // 2. 使用xpath表达式读取nodeList
        NodeList bookNodeList =XmlUtils.evalNodeList("/bookstore/book", document, xpath);
        Node bookNode=null;
        for(int i=0; i<bookNodeList.getLength(); i++){
            bookNode=bookNodeList.item(i);
            Assert.assertEquals("book", bookNode.getNodeName());
        }


        // 3. 使用xpath表达式从节点读取nodeList
        bookNodeList=XmlUtils.evalNodeList("/book", rootNode, xpath);
        for(int i=0; i<bookNodeList.getLength(); i++){
            bookNode=bookNodeList.item(i);
            Assert.assertEquals("book", bookNode.getNodeName());
        }



        // 4. 使用xpath表达式读取属性 数组表达式从1开始, /@ 修饰获取属性
        String lang=XmlUtils.evalString("/bookstore/book[1]/title/@lang", document, xpath);
        Assert.assertEquals("en", lang);

        lang=XmlUtils.evalString("/bookstore/book[2]/title/@lang", document, xpath);
        Assert.assertEquals("cn", lang);
    }




    // --------------------------------- 转换

    @Test
    public void xmlToJSONObjectTest() throws IOException {
        BufferedInputStream bis=FileUtil.getInputStream("xml/bookstore.xml");
        String xmlStr=StreamUtils.copyToString(bis, Charset.forName("utf-8"));



        JSONObject jso=XmlUtils.toJSONObject(xmlStr);


        Assert.assertTrue(jso.getJSONObject("bookstore")!=null);


        Assert.assertTrue(jso.getJSONObject("bookstore").getJSONArray("book")!=null);
    }





    @Test
    public void nodeToJSONObjectTest(){
        BufferedInputStream bis=FileUtil.getInputStream("xml/bookstore.xml");
        Document document=XmlUtils.readXml(bis);


        JSONObject jso=XmlUtils.toJSONObject(document);

        Assert.assertTrue(jso.getJSONObject("bookstore")!=null);


        Assert.assertTrue(jso.getJSONObject("bookstore").getJSONArray("book")!=null);
    }


    @Test
    public void toBeanTest(){
        BufferedInputStream bis=FileUtil.getInputStream("xml/bookstore.xml");
        Document document=XmlUtils.readXml(bis);

        XmlBookstoreDto dto=XmlUtils.toBean(document, XmlBookstoreDto.class);


        Bookstore bookstore=dto.getBookstore();
        Assert.assertNotNull(bookstore);


        List<Book> bookList=bookstore.getBook();

        Book book1=bookList.get(0);
        Assert.assertTrue(book1.getTitle().getLang().equals("en"));
        Assert.assertTrue(book1.getTitle().getContent().equals("Harry Potter"));
        Assert.assertTrue(book1.getAuthor().equals("J K. Rowling"));

        Book book2=bookList.get(1);
        Assert.assertTrue(book2.getTitle().getLang().equals("cn"));
        Assert.assertTrue(book2.getTitle().getContent().equals("where I am from"));
        Assert.assertTrue(book2.getAuthor().equals("timfruit"));

    }