本工具类基于 W3C 的 DOM 包,也就是 org.w3c.dom
DOM 中常见类或接口
DocumentBuilderFactory
:用于创建 DocumentBuilder
对象的工厂类DocumentBuilder
:用于解析 XML 文档,创建 Document
对象的工具类Document
:表示整个 XML 文档,可以理解为一种特殊的节点,是所有节点的根节点Node
:代表 XML 文档中的节点,包括元素节点、属性节点、文本节点等Element
:继承自 Node
,表示 XML 文档中的元素节点Attr
:继承自 Node
,代表 XML 文档中的属性节点Text
:继承自 Node
,代表 XML 文档中的文本节点DOM 中节点列表(NodeList
,只读且长度固定)的常用方法
getLength()
:获取 NodeList
中节点的数量item(int index)
:按照索引值获取 NodeList
中指定位置的节点,返回 Node
对象NodeList
本身没有定义添加或移除节点的方法,这部分需自己实现DOM 中节点(Node
)的常用方法
getNodeName()
:获取节点的名称getNodeType()
:获取节点的类型,如元素、属性、文本、注释等getTextContent()
:获取当前节点的文本内容getParentNode()
:获取当前节点的父节点hasChildNodes()
:判断当前节点是否有子节点getChildNodes()
:获取当前节点的所有子节点getFirstChild()
:获取第一个子节点getLastChild()
:获取最后一个子节点getNextSibling()
:获取下一个兄弟节点getPreviousSibling()
:获取上一个兄弟节点appendChild(Node newChild)
:向元素的子节点列表末尾添加一个新的子节点removeChild(Node oldChild)
:从元素的子节点列表中删除指定的子节点replaceChild(Node newChild, Node oldChild)
:用新的子节点替换元素的指定子节点DOM 中元素(Element
)的常用方法
getTagName()
:获取元素的标签名getAttributes()
:返回元素的属性列表hasAttribute(String name)
:检查元素是否具有指定名称的属性getAttribute(String name)
:获取元素的指定属性的值setAttribute(String name, String value)
:设置元素的指定属性值removeAttribute(String name)
:删除指定属性名的属性getElementsByTagName(String name)
:返回所有指定标签名的子元素节点列表getAttributeNode(String name)
:返回指定属性名的属性节点DOM 中属性(Attr
)的常用方法
getName()
:获取属性的名称getValue()
:获取属性的值setValue(String value)
:设置属性的值getOwnerElement()
:获取拥有此属性的元素节点DOM 中文本(Text
)的常用方法
getData()
:获取文本节点的内容setData(String data)
:设置文本节点的内容以上方法笔者觉得没有必要再封装进工具类了,直接调用就行
而其他的处理可以参考笔者的 XML 处理工具类 XMLUtils
的以下方法
nodeListToList()
:将节点列表转换为元素为节点的列表listToNodeList()
:将元素为节点的列表转换为节点列表nodeToElement()
:将节点转换为元素节点nodeToAttr()
:将节点转换为属性节点nodeToText()
:将节点转换为文本节点elementToNode()
:将元素节点转换为节点attrToNode()
:将属性节点转换为节点textToNode()
:将文本节点转换为节点strToDoc()
:将 XML 字符串转换为文档对象docToStr()
:将文档对象转换为 XML 字符串getChildNodes()
:获取给定节点的所有子节点getChildElements()
:获取给定元素的所有子元素getElementAttrs()
:获取给定元素的所有属性readXMLFile()
:读取 XML 文件并返回文档对象printXML()
:打印 XMLimport org.w3c.dom.*;
import org.xml.sax.InputSource;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.ArrayList;
import java.util.List;public class XMLUtils {private static final DocumentBuilderFactory documentBuilderFactory;private static final TransformerFactory transformerFactory;private static final DocumentBuilder documentBuilder;static {documentBuilderFactory = DocumentBuilderFactory.newInstance();documentBuilderFactory.setNamespaceAware(false);documentBuilderFactory.setValidating(false);transformerFactory = TransformerFactory.newInstance();try {documentBuilder = documentBuilderFactory.newDocumentBuilder();} catch (ParserConfigurationException e) {throw new RuntimeException("无法创建 DOM 解析器", e);}}/*** 自定义的 NodeList 实现类*/private static class NodeListImpl implements NodeList {private final List nodes = new ArrayList<>();/*** 添加节点到 NodeList 中* @param node 要添加的节点*/private void addItem(Node node) {nodes.add(node);}@Overridepublic Node item(int index) {return nodes.get(index);}@Overridepublic int getLength() {return nodes.size();}}/*** 将 NodeList 转换为 List* @param nodeList 要转换的 NodeList 对象* @return 转换后的 List*/public static List nodeListToList(NodeList nodeList) {List list = new ArrayList<>();for (int i = 0; i < nodeList.getLength(); i++) {list.add(nodeList.item(i));}return list;}/*** 将 List 转换为 NodeList* @param list 要转换的 List 对象* @return 转换后的 NodeList*/public static NodeList listToNodeList(List list) {NodeListImpl nodeList = new NodeListImpl();for (Node node : list) {nodeList.addItem(node);}return nodeList;}/*** 将 Node 转换为 Element* @param node 要转换的节点* @return 转换后的元素节点*/public static Element nodeToElement(Node node) {try {if (node.getNodeType() != Node.ELEMENT_NODE) {throw new IllegalArgumentException("该节点不是元素节点");}return (Element) node;} catch (IllegalArgumentException e) {e.printStackTrace();return null;}}/*** 将 Node 转换为 Attr* @param node 要转换的节点* @return 转换后的属性节点*/public static Attr nodeToAttr(Node node) {try {if (node.getNodeType() != Node.ATTRIBUTE_NODE) {throw new IllegalArgumentException("该节点不是属性节点");}return (Attr) node;} catch (IllegalArgumentException e) {e.printStackTrace();return null;}}/*** 将 Node 转换为 Text* @param node 要转换的节点* @return 转换后的文本节点*/public static Text nodeToText(Node node) {try {if (node.getNodeType() != Node.TEXT_NODE) {throw new IllegalArgumentException("该节点不是文本节点");}return (Text) node;} catch (IllegalArgumentException e) {e.printStackTrace();return null;}}/*** 将 Element 转换为 Node* @param element 要转换的元素节点* @return 转换后的节点*/public static Node elementToNode(Element element) {return element;}/*** 将 Attr 转换为 Node* @param attr 要转换的属性节点* @return 转换后的节点*/public static Node attrToNode(Attr attr) {return attr;}/*** 将 Text 转换为 Node* @param text 要转换的文本节点* @return 转换后的节点*/public static Node textToNode(Text text) {return text;}/*** 将 XML 字符串转换为 Document 对象* @param xmlStr XML 字符串* @return Document 对象*/public static Document strToDoc(String xmlStr) {try {// 创建一个 InputSource 对象来包装 XML 字符串InputSource inputSource = new InputSource(new StringReader(xmlStr));// 解析 XML 字符串并返回 Document 对象Document document = documentBuilder.parse(inputSource);// 将文档标准化document.normalize();return document;} catch (Exception e) {e.printStackTrace();return null;}}/*** 将 Document 对象转换为 XML 字符串* @param document 要转换的 Document 对象* @return 转换后的 XML 字符串*/public static String docToStr(Document document) {String xmlStr = "";try {// 创建一个新的转换器对象Transformer transformer = transformerFactory.newTransformer();// 设置转换器属性transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");// 创建一个字符输出流StringWriter writer = new StringWriter();// 将 Document 对象转换为 XML 字符串,并写入字符输出流transformer.transform(new DOMSource(document), new StreamResult(writer));// 将字符输出流转换为字符串并赋值给 xmlStrxmlStr = writer.toString();} catch (Exception e) {e.printStackTrace();}return xmlStr;}/*** 获取指定节点的所有子节点* @param node 父节点* @return 所有子节点列表*/public static List getChildNodes(Node node) {List childNodes = new ArrayList<>();// 获取所有子节点NodeList nodeList = node.getChildNodes();// 遍历所有子节点for (int i = 0; i < nodeList.getLength(); i++) {Node childNode = nodeList.item(i);childNodes.add(childNode);}return childNodes;}/*** 获取指定元素的所有子元素* @param element 父元素* @return 所有子元素列表*/public static List getChildElements(Element element) {List childElements = new ArrayList<>();// 获取所有子节点NodeList nodeList = element.getChildNodes();// 遍历所有子节点for (int i = 0; i < nodeList.getLength(); i++) {Node childNode = nodeList.item(i);// 判断节点类型是否为元素节点if (childNode.getNodeType() == Node.ELEMENT_NODE) {// 将元素节点添加到列表中childElements.add((Element) childNode);}}return childElements;}/*** 获取元素所有属性* @param element 元素节点* @return 属性列表*/public static List getElementAttrs(Element element) {List attributes = new ArrayList<>();// 获取元素的属性集合NamedNodeMap attributeMap = element.getAttributes();// 遍历属性集合for (int i = 0; i < attributeMap.getLength(); i++) {Node attributeNode = attributeMap.item(i);// 判断节点类型是否为属性节点if (attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {// 将属性节点添加到列表中attributes.add((Attr) attributeNode);}}return attributes;}/*** 从指定文件名读取 XML 文件并返回 Document 对象* @param filename XML 文件名* @return Document 对象*/public static Document readXMLFile(String filename) {// 创建一个文件对象File xmlFile = new File(filename);try {// 创建一个FileInputStream对象FileInputStream fis = new FileInputStream(xmlFile);// 解析XML文件并返回Document对象Document doc = documentBuilder.parse(fis);return doc;} catch (Exception e) {e.printStackTrace();return null;}}/*** 打印 XML 文档* @param doc XML文档对象*/public static void printXML(Document doc) {Element root = doc.getDocumentElement();printXML(System.out, root, 0);}/*** 打印 XML 元素及其属性、子元素* @param element XML元素*/public static void printXML(Element element) {printXML(System.out, element, 0);}private static void printXML(PrintStream ps, Element element, int indent) {printTrunk(ps, indent);ps.printf("├─ 元素: %s\n", element.getNodeName());NamedNodeMap attributes = element.getAttributes();for (int i = 0; i < attributes.getLength(); i++) {Attr attribute = (Attr) attributes.item(i);printTrunk(ps, indent + 1);ps.printf("├─ 属性: %s = %s\n", attribute.getName(), attribute.getValue());}NodeList children = element.getChildNodes();for (int i = 0; i < children.getLength(); i++) {Node child = children.item(i);if (child.getNodeType() == Node.ELEMENT_NODE) {printXML(ps, (Element) child, indent + 1);} else if (child.getNodeType() == Node.TEXT_NODE) {String text = child.getNodeValue().trim();if (!text.isEmpty()) {printTrunk(ps, indent + 1);ps.printf("└─ 文本: %s\n", text);}}}}/*** 根据缩进层数打印树干,也就是前置"| "* @param ps 打印流* @param indent 缩进层数*/private static void printTrunk(PrintStream ps, int indent) {for (int i = 0; i < indent; i++) {ps.print("| ");}}
}
上一篇:C++入门3:从数组到循环
下一篇:代码随想录---01背包问题