diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/DocumentBuilderUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/DocumentBuilderUtil.java
new file mode 100755
index 000000000..5106e3dad
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/DocumentBuilderUtil.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+import org.dromara.hutool.core.exception.HutoolException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * {@link DocumentBuilder} 工具类
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class DocumentBuilderUtil {
+
+ /**
+ * 创建 DocumentBuilder
+ *
+ * @param namespaceAware 是否打开命名空间支持
+ * @return DocumentBuilder
+ */
+ public static DocumentBuilder createDocumentBuilder(final boolean namespaceAware) {
+ final DocumentBuilder builder;
+ try {
+ builder = createDocumentBuilderFactory(namespaceAware).newDocumentBuilder();
+ } catch (final Exception e) {
+ throw new HutoolException(e, "Create xml document error!");
+ }
+ return builder;
+ }
+
+ /**
+ * 创建{@link DocumentBuilderFactory}
+ *
+ *
+ * @param namespaceAware 是否打开命名空间支持
+ * @return {@link DocumentBuilderFactory}
+ */
+ public static DocumentBuilderFactory createDocumentBuilderFactory(final boolean namespaceAware) {
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+ // 默认打开NamespaceAware,getElementsByTagNameNS可以使用命名空间
+ factory.setNamespaceAware(namespaceAware);
+ return XXEUtil.disableXXE(factory);
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/SAXParserFactoryUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/SAXParserFactoryUtil.java
new file mode 100755
index 000000000..de23ff5fc
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/SAXParserFactoryUtil.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+import javax.xml.parsers.SAXParserFactory;
+
+/**
+ * {@link SAXParserFactory} 工具
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class SAXParserFactoryUtil {
+
+ /**
+ * Sax读取器工厂缓存
+ */
+ private static volatile SAXParserFactory factory;
+
+ /**
+ * 获取全局{@link SAXParserFactory}
+ *
+ *
默认不验证
+ *
默认打开命名空间支持
+ *
+ *
+ * @return {@link SAXParserFactory}
+ */
+ public static SAXParserFactory getFactory() {
+ if (null == factory) {
+ synchronized (SAXParserFactoryUtil.class) {
+ if (null == factory) {
+ factory = createFactory(false, true);
+ }
+ }
+ }
+
+ return factory;
+ }
+
+ /**
+ * 创建{@link SAXParserFactory}
+ *
+ * @param validating 是否验证
+ * @param namespaceAware 是否打开命名空间支持
+ * @return {@link SAXParserFactory}
+ */
+ public static SAXParserFactory createFactory(final boolean validating, final boolean namespaceAware) {
+ final SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(validating);
+ factory.setNamespaceAware(namespaceAware);
+
+ return XXEUtil.disableXXE(factory);
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/UniversalNamespaceCache.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/UniversalNamespaceCache.java
new file mode 100755
index 000000000..da0b5ef76
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/UniversalNamespaceCache.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+import org.dromara.hutool.core.map.BiMap;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * 全局命名空间上下文
+ * 见:https://www.ibm.com/developerworks/cn/xml/x-nmspccontext/
+ *
+ * @author looly
+ */
+public class UniversalNamespaceCache implements NamespaceContext {
+ private static final String DEFAULT_NS = "DEFAULT";
+ private final BiMap prefixUri = new BiMap<>(new HashMap<>());
+
+ /**
+ * This constructor parses the document and stores all namespaces it can
+ * find. If toplevelOnly is true, only namespaces in the root are used.
+ *
+ * @param node source Node
+ * @param toplevelOnly restriction of the search to enhance performance
+ */
+ public UniversalNamespaceCache(final Node node, final boolean toplevelOnly) {
+ examineNode(node.getFirstChild(), toplevelOnly);
+ }
+
+ /**
+ * A single node is read, the namespace attributes are extracted and stored.
+ *
+ * @param node to examine
+ * @param attributesOnly, if true no recursion happens
+ */
+ private void examineNode(final Node node, final boolean attributesOnly) {
+ final NamedNodeMap attributes = node.getAttributes();
+ if (null != attributes) {
+ final int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ final Node attribute = attributes.item(i);
+ storeAttribute(attribute);
+ }
+ }
+
+ if (!attributesOnly) {
+ final NodeList childNodes = node.getChildNodes();
+ //noinspection ConstantConditions
+ if (null != childNodes) {
+ Node item;
+ final int childLength = childNodes.getLength();
+ for (int i = 0; i < childLength; i++) {
+ item = childNodes.item(i);
+ if (item.getNodeType() == Node.ELEMENT_NODE)
+ examineNode(item, false);
+ }
+ }
+ }
+ }
+
+ /**
+ * This method looks at an attribute and stores it, if it is a namespace
+ * attribute.
+ *
+ * @param attribute to examine
+ */
+ private void storeAttribute(final Node attribute) {
+ if (null == attribute) {
+ return;
+ }
+ // examine the attributes in namespace xmlns
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attribute.getNamespaceURI())) {
+ // Default namespace xmlns="uri goes here"
+ if (XMLConstants.XMLNS_ATTRIBUTE.equals(attribute.getNodeName())) {
+ prefixUri.put(DEFAULT_NS, attribute.getNodeValue());
+ } else {
+ // The defined prefixes are stored here
+ prefixUri.put(attribute.getLocalName(), attribute.getNodeValue());
+ }
+ }
+
+ }
+
+ /**
+ * This method is called by XPath. It returns the default namespace, if the
+ * prefix is null or "".
+ *
+ * @param prefix to search for
+ * @return uri
+ */
+ @Override
+ public String getNamespaceURI(final String prefix) {
+ if (prefix == null || XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
+ return prefixUri.get(DEFAULT_NS);
+ } else {
+ return prefixUri.get(prefix);
+ }
+ }
+
+ /**
+ * This method is not needed in this context, but can be implemented in a
+ * similar way.
+ */
+ @Override
+ public String getPrefix(final String namespaceURI) {
+ return prefixUri.getInverse().get(namespaceURI);
+ }
+
+ @Override
+ public Iterator getPrefixes(final String namespaceURI) {
+ // Not implemented
+ return null;
+ }
+
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/XPathUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XPathUtil.java
new file mode 100755
index 000000000..3aac78c56
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XPathUtil.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+import org.dromara.hutool.core.exception.HutoolException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+/**
+ * {@link XPath}相关工具类
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class XPathUtil {
+
+ /**
+ * 创建XPath
+ * Xpath相关文章:https://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html
+ *
+ * @return {@link XPath}
+ * @since 3.2.0
+ */
+ public static XPath createXPath() {
+ return XPathFactory.newInstance().newXPath();
+ }
+
+ /**
+ * 通过XPath方式读取XML节点等信息
+ * Xpath相关文章:https://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html
+ *
+ * @param expression XPath表达式
+ * @param source 资源,可以是Docunent、Node节点等
+ * @return 匹配返回类型的值
+ * @since 4.0.9
+ */
+ public static Element getElementByXPath(final String expression, final Object source) {
+ return (Element) getNodeByXPath(expression, source);
+ }
+
+ /**
+ * 通过XPath方式读取XML的NodeList
+ * Xpath相关文章:https://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html
+ *
+ * @param expression XPath表达式
+ * @param source 资源,可以是Docunent、Node节点等
+ * @return NodeList
+ * @since 4.0.9
+ */
+ public static NodeList getNodeListByXPath(final String expression, final Object source) {
+ return (NodeList) getByXPath(expression, source, XPathConstants.NODESET);
+ }
+
+ /**
+ * 通过XPath方式读取XML节点等信息
+ * Xpath相关文章:https://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html
+ *
+ * @param expression XPath表达式
+ * @param source 资源,可以是Docunent、Node节点等
+ * @return 匹配返回类型的值
+ * @since 4.0.9
+ */
+ public static Node getNodeByXPath(final String expression, final Object source) {
+ return (Node) getByXPath(expression, source, XPathConstants.NODE);
+ }
+
+ /**
+ * 通过XPath方式读取XML节点等信息
+ * Xpath相关文章:https://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html
+ *
+ * @param expression XPath表达式
+ * @param source 资源,可以是Docunent、Node节点等
+ * @param returnType 返回类型,{@link javax.xml.xpath.XPathConstants}
+ * @return 匹配返回类型的值
+ * @since 3.2.0
+ */
+ public static Object getByXPath(final String expression, final Object source, final QName returnType) {
+ NamespaceContext nsContext = null;
+ if (source instanceof Node) {
+ nsContext = new UniversalNamespaceCache((Node) source, false);
+ }
+ return getByXPath(expression, source, returnType, nsContext);
+ }
+
+ /**
+ * 通过XPath方式读取XML节点等信息
+ * Xpath相关文章:
+ * https://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html
+ * https://www.ibm.com/developerworks/cn/xml/x-nmspccontext/
+ *
+ * @param expression XPath表达式
+ * @param source 资源,可以是Docunent、Node节点等
+ * @param returnType 返回类型,{@link javax.xml.xpath.XPathConstants}
+ * @param nsContext {@link NamespaceContext}
+ * @return 匹配返回类型的值
+ * @since 5.3.1
+ */
+ public static Object getByXPath(final String expression, final Object source, final QName returnType, final NamespaceContext nsContext) {
+ final XPath xPath = createXPath();
+ if (null != nsContext) {
+ xPath.setNamespaceContext(nsContext);
+ }
+ try {
+ if (source instanceof InputSource) {
+ return xPath.evaluate(expression, (InputSource) source, returnType);
+ } else {
+ return xPath.evaluate(expression, source, returnType);
+ }
+ } catch (final XPathExpressionException e) {
+ throw new HutoolException(e);
+ }
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/XXEUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XXEUtil.java
new file mode 100755
index 000000000..693b10b14
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XXEUtil.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+import org.dromara.hutool.core.exception.HutoolException;
+import org.dromara.hutool.core.text.StrUtil;
+import org.xml.sax.XMLReader;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+/**
+ * XXE漏洞修复相关工具类
+ * 参考:https://blog.spoock.com/2018/10/23/java-xxe/
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class XXEUtil {
+
+ /**
+ * 关闭XXE,避免漏洞攻击
+ * see: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXP_DocumentBuilderFactory.2C_SAXParserFactory_and_DOM4J
+ *
+ * @param factory DocumentBuilderFactory
+ * @return DocumentBuilderFactory
+ */
+ public static DocumentBuilderFactory disableXXE(final DocumentBuilderFactory factory) {
+ try {
+ // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented
+ // Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
+ factory.setFeature(XmlFeatures.DISALLOW_DOCTYPE_DECL, true);
+ // If you can't completely disable DTDs, then at least do the following:
+ // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
+ // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
+ // JDK7+ - http://xml.org/sax/features/external-general-entities
+ factory.setFeature(XmlFeatures.EXTERNAL_GENERAL_ENTITIES, false);
+ // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
+ // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
+ // JDK7+ - http://xml.org/sax/features/external-parameter-entities
+ factory.setFeature(XmlFeatures.EXTERNAL_PARAMETER_ENTITIES, false);
+ // Disable external DTDs as well
+ factory.setFeature(XmlFeatures.LOAD_EXTERNAL_DTD, false);
+ } catch (final ParserConfigurationException e) {
+ // ignore
+ }
+
+ // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
+ factory.setXIncludeAware(false);
+ factory.setExpandEntityReferences(false);
+
+ return factory;
+ }
+
+ /**
+ * 关闭XEE避免漏洞攻击
+ *
+ * @param factory {@link SAXParserFactory}
+ * @return {@link SAXParserFactory}
+ */
+ public static SAXParserFactory disableXXE(final SAXParserFactory factory) {
+ try {
+ factory.setFeature(XmlFeatures.DISALLOW_DOCTYPE_DECL, true);
+ factory.setFeature(XmlFeatures.EXTERNAL_GENERAL_ENTITIES, false);
+ factory.setFeature(XmlFeatures.EXTERNAL_PARAMETER_ENTITIES, false);
+ factory.setFeature(XmlFeatures.LOAD_EXTERNAL_DTD, false);
+ } catch (final Exception ignore) {
+ // ignore
+ }
+
+ factory.setXIncludeAware(false);
+
+ return factory;
+ }
+
+ /**
+ * 关闭XEE避免漏洞攻击
+ *
+ * @param reader {@link XMLReader}
+ * @return {@link XMLReader}
+ */
+ public static XMLReader disableXXE(final XMLReader reader) {
+ try {
+ reader.setFeature(XmlFeatures.DISALLOW_DOCTYPE_DECL, true);
+ reader.setFeature(XmlFeatures.EXTERNAL_GENERAL_ENTITIES, false);
+ reader.setFeature(XmlFeatures.EXTERNAL_PARAMETER_ENTITIES, false);
+ reader.setFeature(XmlFeatures.LOAD_EXTERNAL_DTD, false);
+ } catch (final Exception ignore) {
+ // ignore
+ }
+
+ return reader;
+ }
+
+ /**
+ * 关闭XEE避免漏洞攻击
+ *
+ * @param factory {@link TransformerFactory }
+ * @return {@link TransformerFactory }
+ */
+ public static TransformerFactory disableXXE(final TransformerFactory factory) {
+ try {
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ } catch (final TransformerConfigurationException e) {
+ throw new HutoolException(e);
+ }
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, StrUtil.EMPTY);
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, StrUtil.EMPTY);
+ return factory;
+ }
+
+ /**
+ * 关闭XEE避免漏洞攻击
+ *
+ * @param validator {@link Validator }
+ * @return {@link Validator }
+ */
+ public static Validator disableXXE(final Validator validator) {
+ try {
+ validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, StrUtil.EMPTY);
+ validator.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, StrUtil.EMPTY);
+ } catch (final Exception ignore) {
+ // ignore
+ }
+ return validator;
+ }
+
+ /**
+ * 关闭XEE避免漏洞攻击
+ *
+ * @param factory {@link SAXTransformerFactory}
+ * @return {@link SAXTransformerFactory}
+ */
+ public static SAXTransformerFactory disableXXE(final SAXTransformerFactory factory) {
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, StrUtil.EMPTY);
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, StrUtil.EMPTY);
+ return factory;
+ }
+
+ /**
+ * 关闭XEE避免漏洞攻击
+ *
+ * @param factory {@link SchemaFactory}
+ * @return {@link SchemaFactory}
+ */
+ public static SchemaFactory disableXXE(final SchemaFactory factory) {
+ try {
+ factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, StrUtil.EMPTY);
+ factory.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, StrUtil.EMPTY);
+ } catch (final Exception ignore) {
+ // ignore
+ }
+ return factory;
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlConstants.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlConstants.java
new file mode 100755
index 000000000..c281aeb8c
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlConstants.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+import java.util.regex.Pattern;
+
+/**
+ * XML相关常量
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class XmlConstants {
+ /**
+ * 字符串常量:XML 不间断空格转义 {@code " " -> " "}
+ */
+ public static final String NBSP = " ";
+
+ /**
+ * 字符串常量:XML And 符转义 {@code "&" -> "&"}
+ */
+ public static final String AMP = "&";
+
+ /**
+ * 字符串常量:XML 双引号转义 {@code """ -> "\""}
+ */
+ public static final String QUOTE = """;
+
+ /**
+ * 字符串常量:XML 单引号转义 {@code "&apos" -> "'"}
+ */
+ public static final String APOS = "'";
+
+ /**
+ * 字符串常量:XML 小于号转义 {@code "<" -> "<"}
+ */
+ public static final String LT = "<";
+
+ /**
+ * 字符串常量:XML 大于号转义 {@code ">" -> ">"}
+ */
+ public static final String GT = ">";
+
+ /**
+ * 在XML中无效的字符 正则
+ */
+ public static final Pattern INVALID_PATTERN = Pattern.compile("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]");
+ /**
+ * 在XML中注释的内容 正则
+ */
+ public static final Pattern COMMENT_PATTERN = Pattern.compile("(?s)");
+ /**
+ * XML格式化输出默认缩进量
+ */
+ public static final int INDENT_DEFAULT = 2;
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlFeatures.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlFeatures.java
new file mode 100755
index 000000000..c1fbdcf38
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlFeatures.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+/**
+ * XXE安全相关参数
+ * 见:https://blog.spoock.com/2018/10/23/java-xxe/
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class XmlFeatures {
+
+ /**
+ * 禁用xml中的inline DOCTYPE 声明,即禁用DTD
+ * 不允许将外部实体包含在传入的 XML 文档中,从而防止XML实体注入(XML External Entities 攻击,利用能够在处理时动态构建文档的 XML 功能,注入外部实体)
+ */
+ public static final String DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
+ /**
+ * 忽略外部DTD
+ */
+ public static final String LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+ /**
+ * 不包括外部一般实体
+ */
+ public static final String EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
+ /**
+ * 不包含外部参数实体或外部DTD子集。
+ */
+ public static final String EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlMapper.java b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlMapper.java
new file mode 100755
index 000000000..5d0f0f6f6
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/xml/XmlMapper.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.xml;
+
+import org.dromara.hutool.core.bean.BeanUtil;
+import org.dromara.hutool.core.collection.CollUtil;
+import org.dromara.hutool.core.collection.ListUtil;
+import org.dromara.hutool.core.map.MapUtil;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * XML转换器,用于转换Map或Bean等
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class XmlMapper {
+
+ /**
+ * 创建XmlMapper
+ *
+ * @param node {@link Node}XML节点
+ * @return XmlMapper
+ */
+ public static XmlMapper of(final Node node) {
+ return new XmlMapper(node);
+ }
+
+ private final Node node;
+
+ /**
+ * 构造
+ *
+ * @param node {@link Node}XML节点
+ */
+ public XmlMapper(final Node node) {
+ this.node = node;
+ }
+
+ /**
+ * XML转Java Bean
+ * 如果XML根节点只有一个,且节点名和Bean的名称一致,则直接转换子节点
+ *
+ * @param bean类型
+ * @param bean bean类
+ * @return bean
+ * @since 5.2.4
+ */
+ public T toBean(final Class bean) {
+ final Map map = toMap();
+ if (null != map && map.size() == 1) {
+ final String nodeName = CollUtil.getFirst(map.keySet());
+ if (bean.getSimpleName().equalsIgnoreCase(nodeName)) {
+ // 只有key和bean的名称匹配时才做单一对象转换
+ return BeanUtil.toBean(CollUtil.get(map.values(), 0), bean);
+ }
+ }
+ return BeanUtil.toBean(map, bean);
+ }
+
+ /**
+ * XML节点转Map
+ *
+ * @return map
+ */
+ public Map toMap() {
+ return toMap(new LinkedHashMap<>());
+ }
+
+ /**
+ * XML节点转Map
+ *
+ * @param result 结果Map
+ * @return map
+ */
+ public Map toMap(final Map result) {
+ return toMap(this.node, result);
+ }
+
+ /**
+ * XML节点转Map
+ *
+ * @param result 结果Map
+ * @return map
+ */
+ @SuppressWarnings("unchecked")
+ private static Map toMap(final Node node, Map result) {
+ if (null == result) {
+ result = new HashMap<>();
+ }
+ final NodeList nodeList = node.getChildNodes();
+ final int length = nodeList.getLength();
+ Node childNode;
+ Element childEle;
+ for (int i = 0; i < length; ++i) {
+ childNode = nodeList.item(i);
+ if (!XmlUtil.isElement(childNode)) {
+ continue;
+ }
+
+ childEle = (Element) childNode;
+ final Object value = result.get(childEle.getNodeName());
+ final Object newValue;
+ if (childEle.hasChildNodes()) {
+ // 子节点继续递归遍历
+ final Map map = toMap(childEle, new LinkedHashMap<>());
+ if (MapUtil.isNotEmpty(map)) {
+ newValue = map;
+ } else {
+ newValue = childEle.getTextContent();
+ }
+ } else {
+ newValue = childEle.getTextContent();
+ }
+
+ if (null != newValue) {
+ if (null != value) {
+ if (value instanceof List) {
+ ((List