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")); }