- List item
Article directory
- Notes on manipulating Xml in Java
-
- 1. Introduction to the use of XmlUtil in Hutool
- 2. XmlUtil in Hutool quickly reads the value of a certain node in an Xml string [recommended for simple values]
-
- 2-1 Hutool toolkit Maven dependencies and test Xml strings are as follows
- 2-2 Read the value of the node
in Xml
- 3. Detailed operation example of XmlUtil in Hutool
-
- 3-1 Xml sample string is as follows
- 3-2 Query attributes in tags
- 3-3 Query the text in a pair of tags
- 3-4 After querying Xml, add a new tag and assign it
- 3-5 Modify a label data
- 4 Rely on the tool class XmlUtil re-encapsulated by Hutool to realize xml-map, map-xml, xml-json functions
-
- 4-1 Dependencies that need to be added
- 4-2 Tool class XmlUtil code
-
- An enumeration XmlSort used in 4-2-1 is as follows:
- 4-2-2 XmlUtil.java is as follows
- 5 Interchange between JavaBean and Xml_Using XStream to achieve, very practical [strongly recommended]
-
- 5-1 Introduce XStream dependency
- 5-2 Tool class XStreamXmlBeanUtil
- 5-3 Use cases
Notes on using Xml in Java
1. Introduction to the use of XmlUtil in Hutool
# Explanation 1: XmlUtil is just a simple tool package of w3c dom, which reduces the difficulty of operating dom. # If the project relies heavily on XML, the Dom4j framework is still recommended # Description 2: JDK has been packaged with XML parsing and construction tools: w3c dom # XmlUtil in Hutool simplifies the creation, reading and writing of XML 1. Read XML Reading XML is divided into two methods: XmlUtil.readXML read XML file XmlUtil.parseXml parses XML strings into Document objects \t 2. Write XML XmlUtil.toStr converts XML documents to String XmlUtil.toFile writes an XML document to a file \t 3. Create XML XmlUtil.createXml creates XML documents, and the created XML defaults to utf8 encoding. The process of modifying the encoding is in the toStr and toFile methods, that is, the encoding is only defined when XML is converted into text. 4. XML read operation Through the following tool methods, basic node read operations can be completed. XmlUtil.cleanInvalid removes invalid characters in XML text XmlUtil.getElements obtains the list of child nodes according to the node name XmlUtil.getElement gets the first child node according to the node name XmlUtil.elementText gets the first child node according to the node name XmlUtil.transElements converts NodeList to Element list \t\t 5. XML and object conversion writeObjectAsXml converts a serializable object to XML and writes it to a file. Existing files will be overwritten. readObjectFromXml reads an object from XML. Note that these two methods rely heavily on JDK's XMLEncoder and XMLDecoder, Generation and parsing must exist in pairs (following a fixed format), and ordinary XML to Bean will report an error. 6. XPath operation createXPath creates XPath getByXPath reads information such as XML nodes through XPath
2. XmlUtil in Hutool quickly reads the value of a node in an Xml string [recommended for simple values]
2-1 Hutool toolkit Maven dependencies and test Xml strings are as follows
<!-- Introduce Hutool's Maven dependency --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency>
<!-- Xml string for the test below --> <?xml version="1.0" encoding="utf-8"?> <returnsms> <returnstatus>Success</returnstatus> <message>ok</message> <remainpoint>1490</remainpoint> <taskID>885</taskID> <successCounts>1</successCounts> </returnsms>
2-2 Read the value of the node in Xml
Document docResult=XmlUtil. readXML(xmlFile); // The result is "ok" Object value = XmlUtil.getByXPath("//returnsms/message", docResult, XPathConstants.STRING); // Note: Element objects currently only support layer-by-layer downward parsing, so please do not skip levels to do queries. // Otherwise, null will be reported. If you want to directly get the text of a label, with accurate positioning // You can directly write the path to get, // But if the same label exists in this level, only the data of the first label will be obtained. String xmlData="xml string"; Document document = XmlUtil. parseXml(xmlData); // Get the root node of the XML document Element elementG=XmlUtil. getRootElement(document); // Get the data through a fixed path Object bString = XmlUtil.getByXPath("//root/base/message/event_no", document, XPathConstants.STRING); System.out.println("event_no element node value: " + bString);
3. Detailed operation example of XmlUtil in Hutool
3-1 Xml sample string is as follows
<forms version="2.1"> <formExport> <summary id="1132755668421070367" name="formmain_0031"/> <definitions> <column id="field0001" type="0" name="field1" length="255"/> <column id="field0002" type="0" name="field2" length="256"/> </definitions> <values> <column name="field1"> <value> CCB I </value> </column> <column name="field2"> <value> Chinese people </value> </column> </values> <subForms/> </formExport> </forms>
3-2 Query attributes in tags
// Example: Get the value of the length attribute of the first tag <column> in the <definitions> tag String xmlData="the xml string specified above"; // replace it by yourself during the test Document document = XmlUtil. parseXml(xmlData); // Get the root node of the XML document Element elementG=XmlUtil. getRootElement(document); // print node name System.out.println(elementG.getTagName()); // Get the lower node (this method takes the first one by default) Element elementZ=XmlUtil.getElement(elementG,"formExport"); System.out.println(elementZ.getTagName()); // Get the lower node (this method takes the first one by default) Element elementZ1=XmlUtil.getElement(elementZ,"definitions"); System.out.println(elementZ1.getTagName()); // Get the lower node (this method takes the first one by default) Element elementZ2=XmlUtil.getElement(elementZ1,"column"); System.out.println(elementZ2.getTagName()); //Read attribute length System.out.println(elementZ2.getAttribute("length"));
3-3 Query the text in a pair of tags
// Example: Get the text contained in <value> under the first tag <column> in the <values> tag, you can directly see the last line // ======= The following content is the same as 3-2, and the content starts =================================== ======== String xmlData="the xml string specified above"; Document document = XmlUtil. parseXml(xmlData); // Get the root node of the XML document Element elementG=XmlUtil. getRootElement(document); // Get the lower node (this method takes the first one by default) Element elementZ=XmlUtil.getElement(elementG,"formExport"); // Get the lower node (this method takes the first one by default) Element elementZ_1=XmlUtil.getElement(elementZ,"values"); // Get the lower node (this method takes the first one by default) Element elementZ_2=XmlUtil.getElement(elementZ_1,"column"); // ======= The above content is the same as 3-2, the content ends =================================== ======== // Get all sub-tags // NodeList when Value is returned, just traverse to get it NodeList nodeList=elementZ_2.getElementsByTagName("value"); for (int i = 0; i <nodeList.getLength() ; i ++ ) {<!-- --> // print the text of the label System.out.println(nodeList.item(i).getTextContent()); }
3-4 After querying Xml, add a new tag and assign a value
// Example: Add another <value> tag under the first tag <column> in the <values> tag, and the contained text is: start from zero // ======= The following content is the same as 3-2, and the content starts =================================== ======== String xmlData="the xml string specified above"; Document document = XmlUtil. parseXml(xmlData); // Get the root node of the XML document Element elementG=XmlUtil. getRootElement(document); // Get the lower node (this method takes the first one by default) Element elementZ=XmlUtil.getElement(elementG,"formExport"); // Get the lower node (this method takes the first one by default) Element elementZ_1=XmlUtil.getElement(elementZ,"values"); // Get the lower node (this method takes the first one by default) Element elementZ_2=XmlUtil.getElement(elementZ_1,"column"); // ======= The above content is the same as 3-2, the content ends =================================== ======== // create a label Element elementItem = document. createElement("value"); //assignment elementItem.setTextContent("Start from zero"); // put it under a label elementZ_2.appendChild(elementItem); //Get all subtags NodeList nodeList=elementZ_2.getElementsByTagName("value"); for (int i = 0; i <nodeList.getLength() ; i ++ ) {<!-- --> // print the text of the label System.out.println(nodeList.item(i).getTextContent()); } System.out.println(XmlUtil.toStr(document)); // Printed result: After <value>CCB I</value>, a new <value>starts from zero</value>
3-5 modify a tag data
// Example: Modify the first <value> tag under the first tag <column> in the <values> tag to: Zhang Sanfeng // ======= The following content is the same as 3-2, and the content starts =================================== ======== String xmlData="the xml string specified above"; Document document = XmlUtil. parseXml(xmlData); // Get the root node of the XML document Element elementG=XmlUtil. getRootElement(document); // Get the lower node (this method takes the first one by default) Element elementZ=XmlUtil.getElement(elementG,"formExport"); // Get the lower node (this method takes the first one by default) Element elementZ_1=XmlUtil.getElement(elementZ,"values"); // Get the lower node (this method takes the first one by default) Element elementZ_2=XmlUtil.getElement(elementZ_1,"column"); // ======= The above content is the same as 3-2, the content ends =================================== ======== //Get all subtags NodeList nodeList=elementZ_2.getElementsByTagName("value"); // first print for (int i = 0; i <nodeList.getLength() ; i ++ ) {<!-- --> // print the text of the label System.out.println(nodeList.item(i).getTextContent()); } //Revise for (int i = 0; i <nodeList.getLength() ; i ++ ) {<!-- --> // ******************* Modify here ********************* nodeList.item(i).setTextContent("Zhang Sanfeng"); } // second print for (int i = 0; i <nodeList.getLength() ; i ++ ) {<!-- --> // print the text of the label System.out.println(nodeList.item(i).getTextContent()); } // print out the result: // The first print output is: CCB I // The second printout is: Zhang Sanfeng
4 Rely on the tool class XmlUtil re-encapsulated by Hutool to realize xml-map, map-xml, xml-json functions
// Function: // 1.xml to map // 2.xml to json // 3. map to xml
4-1 Dependencies that need to be added
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.15</version> </dependency> <dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.3</version> </dependency>
4-2 Tool class XmlUtil code
An enumeration XmlSort used in 4-2-1 is as follows:
import java.util.HashMap; import java.util.LinkedHashMap; /** * Whether the xml parsing order is in order * @author ASen */ public enum XmlSort{<!-- --> /** * orderly */ SORT(LinkedHashMap.class,"Ordered"), /** * Disorder */ NO_SORT(HashMap.class,"Unordered"); /** * Created map bytecode object */ private final Class<?> mapClass; /** * sequence name */ private final String message; XmlSort(Class<?> mapClass, String message) {<!-- --> this. mapClass = mapClass; this. message = message; } public Class<?> getMapClass() {<!-- --> return mapClass; } public String getMessage() {<!-- --> return message; } }
4-2-2 XmlUtil.java is as follows
package com.asen.demo.util; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.asen.demo.constant.XmlSort; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.dom4j.tree.DefaultDocument; import org.dom4j.tree.DefaultElement; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; /** * xml parsing helper class * @author asen * @date 2022/1/10 15:17 */ public class XmlUtil {<!-- --> /** * Label attribute */ private final static String TAG_ATTR = "attr"; /** * The type of map created */ private XmlSort xmlSort = XmlSort.NO_SORT; /** * map to xml * @param map map object * @return xml string */ public String mapToXml(Map<String,Object> map) {<!-- --> if(map. size() != 1){<!-- --> throw new RuntimeException("map root node length is not 1"); } String key = ""; for (String str : map. keySet()) {<!-- --> key = str; } // create root node Element rootElement = new DefaultElement(key); Document document = new DefaultDocument(rootElement); Element node = document. getRootElement(); Object obj = map. get(key); // assert Assert.isAssignable(Map.class, obj.getClass()); mapNodes(node,(Map<String, Object>)obj); return document.asXML(); } /** * The parent class node has been created, and the map contains the parent class * @param node node * @param map map */ public void mapNodes(Element node, Map<String, Object> map) {<!-- --> map.forEach((k,v)->{<!-- --> Object obj = map. get(k); // Add properties to the current parent class if(TAG_ATTR.equals(k)){<!-- --> Assert.isAssignable(Map.class, obj.getClass()); Map<String,Object> tagMap = (Map<String,Object>) obj; tagMap.forEach((tagKey,tagValue)->{<!-- --> node.addAttribute(tagKey, (String) tagValue); }); return; } if(obj instanceof Map){<!-- --> Element newElement = node. addElement(k); // map processing Map<String,Object> childMap = (Map<String,Object>) obj; mapNodes(newElement, childMap); }else if (obj instanceof String){<!-- --> Element newElement = node. addElement(k); newElement. setText((String) v); } else if (obj instanceof List) {<!-- --> List<Map<String, Object>> list = (List<Map<String, Object>>) obj; list.forEach(itemMap->{<!-- --> Element newElement = node. addElement(k); mapNodes(newElement, itemMap); }); } }); } /** * Read the xml file and return the json string * * @param fileName file path * @return json string * @throws DocumentException exception */ public String xmlToJson(String fileName) throws DocumentException {<!-- --> Map<String, Object> xmlMap = xmlToMap(fileName); return JSONUtil.toJsonStr(xmlMap); } /** * Read the xml file and return the map object * * @param fileName file path * @return map object * @throws DocumentException exception */ public Map<String, Object> xmlToMap(String fileName) throws DocumentException {<!-- --> // create saxReader object SAXReader reader = new SAXReader(); // Read a file through the read method and convert it into a Document object Document document = reader. read(new File(fileName)); // Get the root node element object Element node = document. getRootElement(); //Loop through all element nodes Map<String, Object> map = getNewMap(); // process node listNodes(node, map); return map; } /** * Traversing all (element's) child nodes below the current node element * * @param node node */ public void listNodes(Element node, Map<String, Object> map) {<!-- --> Map<String, Object> xiaoMap = getNewMap(); String nodeKey = node. getName(); // Get all attribute nodes of the current node List<Attribute> list = node.attributes(); // loop through attribute nodes Map<String, Object> attrMap = getNewMap(); for (Attribute attr : list) {<!-- --> attrMap.put(attr.getName(), attr.getValue()); } if (ObjectUtil.isNotEmpty(attrMap)) {<!-- --> xiaoMap.put(TAG_ATTR, attrMap); } // Child node iterator below the current node Iterator<Element> it = node. elementIterator(); if (!("".equals(node.getTextTrim())) || !it.hasNext()) {<!-- --> map.put(nodeKey, node.getTextTrim()); }else{<!-- --> // not null if (ObjectUtil.isEmpty(map.get(nodeKey))) {<!-- --> map.put(nodeKey, xiaoMap); } else {<!-- --> List<Map<String, Object>> childList = null; // get the original Object obj = map. get(nodeKey); if (obj instanceof Iterable) {<!-- --> // not the first childList = (List<Map<String, Object>>) obj; childList.add(xiaoMap); } else if (obj instanceof Map) {<!-- --> // First Map<String, Object> childMap = (Map<String, Object>) obj; childList = new ArrayList<>(); childList.add(childMap); childList.add(xiaoMap); } // add new map. put(nodeKey, childList); } } // traverse while (it.hasNext()) {<!-- --> // Get a child node object Element e = it. next(); // traverse the child nodes listNodes(e, xiaoMap); } } /** * Get a new map object * * @return map object */ private Map<String, Object> getNewMap() {<!-- --> Object obj = null; try {<!-- --> obj = xmlSort.getMapClass().newInstance(); if (obj instanceof Map) {<!-- --> return (Map<String, Object>) obj; } } catch (InstantiationException | IllegalAccessException e) {<!-- --> e.printStackTrace(); } return null; } /** * Set whether to sort * * @param xmlSort Whether to sort objects */ public void setXmlSort(XmlSort xmlSort) {<!-- --> this.xmlSort = xmlSort; } }
5 Interchange between JavaBean and Xml_Using XStream to achieve, very practical [strongly recommended]
Description:
Compared to JAXB, XStream is more concise.
Common annotations:
@XStreamAlias: Define xml node name
5-1 Introduce XStream dependency
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.19</version> </dependency>
5-2 Tool class XStreamXmlBeanUtil
import com.thoughtworks.xstream.XStream; /** * XStream implements conversion between bean and xml */ public class XStreamXmlBeanUtil {<!-- --> /** * JavaBean to XML * @param bean - JavaBean * @return - XML */ public static String toXml(Object bean) {<!-- --> return initXStream(bean. getClass()). toXML(bean); } /** * XML to JavaBean * @param xml - XML * @param beanClazz - JavaBean Class * @param <T> * @return - JavaBean */ @SuppressWarnings("unchecked") public static <T> T fromXml(String xml, Class<T> beanClazz) {<!-- --> return (T) initXStream(beanClazz).fromXML(xml); } private static XStream initXStream(Class<?> beanClazz) {<!-- --> XStream x = new XStream(); x.registerConverter(new DateConverter("yyyy-MM-dd HH:mm:ss", null,TimeZone.getTimeZone("GMT+8"))); \t\t //Do not use the default class loader, you need to manually set the class loader x.setClassLoader(beanClazz.getClassLoader()); x. processAnnotations(beanClazz); x.allowTypesByRegExp(new String[]{<!-- -->".*"}); // Enable annotation function x. autodetectAnnotations(true); // suddenly unknown field x.ignoreUnknownElements(); return x; } }
5-3 Use cases
import com.thoughtworks.xstream.annotations.XStreamAlias; import lombok. AllArgsConstructor; import lombok.Data; import lombok. NoArgsConstructor; public class Test {<!-- --> public static void main(String[] args) {<!-- --> // 1. Common bean and Xml conversion User user = new User("Diao Chan", 18, "Female"); System.out.println("============ normal bean to Xml================="); String xml = XStreamXmlBeanUtil.toXml(user); System.out.println(xml); System.out.println("============Xml to ordinary bean================="); System.out.println(XStreamXmlBeanUtil.fromXml(xml, User.class)); // 2. Inherited bean and Xml exchange Child child = new Child("Eat candied haws"); child.setName("cucurbit baby"); child. setAge(2); child.setGender("Male"); child.setHobby("playing games"); System.out.println("============= inherited bean to Xml================="); xml = XStreamXmlBeanUtil.toXml(child); System.out.println(xml); System.out.println("============Xml to inherit bean===="); // The generated Xml only has the attribute hobby of Child, but the parent attribute of the converted Child object has values; System.out.println(XStreamXmlBeanUtil.fromXml(xml, Child.class)); System.out.println("============Xml to inherit bean, test whether the parent attribute and its own attribute have value===="); Child c2 = XStreamXmlBeanUtil.fromXml(xml, Child.class); System.out.println( "11111==" + c2.getName() + c2.getGender() + c2.getHobby()); \t\t // The output is as follows: // ============= Ordinary bean to Xml================ // <Women> // <name>Diao Chan</name> // <age>18</age> // <gender>female</gender> // </Women> // =============Xml to normal bean================ // XmlTest.User(name=Diaochan, age=18, gender=female) // ============= Inherited bean to Xml================ // <User> // <name>Gourd Baby</name> // <age>2</age> // <gender>Male</gender> // <hobby>playing games</hobby> // </User> // ============Xml to inherit bean==== // XmlTest.Child(hobby=playing games) // 11111==Gourd boy playing games } } @Data @NoArgsConstructor @AllArgsConstructor @XStreamAlias("Women") class User {<!-- --> private String name; private int age; private String gender; } @NoArgsConstructor @AllArgsConstructor @Data @XStreamAlias("User") class Child extends User {<!-- --> private String hobby; }