All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xiaoleilu.hutool.util.XmlUtil Maven / Gradle / Ivy

package com.xiaoleilu.hutool.util;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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 javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.xiaoleilu.hutool.exceptions.UtilException;
import com.xiaoleilu.hutool.io.FileUtil;
import com.xiaoleilu.hutool.io.IoUtil;
import com.xiaoleilu.hutool.lang.Assert;

/**
 * XML工具类
* 此工具使用w3c dom工具,不需要依赖第三方包。
* 工具类封装了XML文档的创建、读取、写出和部分XML操作 * * @author xiaoleilu * */ public class XmlUtil { /** 在XML中无效的字符 正则 */ public final static String INVALID_REGEX = "[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]"; // -------------------------------------------------------------------------------------- Read /** * 读取解析XML文件 * * @param file XML文件 * @return XML文档对象 */ public static Document readXML(File file) { Assert.notNull(file, "Xml file is null !"); if (false == file.exists()) { throw new UtilException("File [{}] not a exist!", file.getAbsolutePath()); } if (false == file.isFile()) { throw new UtilException("[{}] not a file!", file.getAbsolutePath()); } try { file = file.getCanonicalFile(); } catch (IOException e) { //ignore } return readXML(new InputSource(file.toURI().toASCIIString())); } /** * 读取解析XML文件
* 如果给定内容以“<”开头,表示这是一个XML内容,直接读取,否则按照路径处理
* 路径可以为相对路径,也可以是绝对路径,相对路径相对于ClassPath * * @param pathOrContent 内容或路径 * @return XML文档对象 * @since 3.0.9 */ public static Document readXML(String pathOrContent) { if(StrUtil.startWith(pathOrContent, '<')) { return parseXml(pathOrContent); } return readXML(FileUtil.file(pathOrContent)); } /** * 读取解析XML文件
* 编码在XML中定义 * * @param inputStream XML流 * @return XML文档对象 * @throws UtilException IO异常或转换异常 * @since 3.0.9 */ public static Document readXML(InputStream inputStream) throws UtilException{ return readXML(new InputSource(inputStream)); } /** * 读取解析XML文件 * * @param reader XML流 * @return XML文档对象 * @throws UtilException IO异常或转换异常 * @since 3.0.9 */ public static Document readXML(Reader reader) throws UtilException{ return readXML(new InputSource(reader)); } /** * 读取解析XML文件
* 编码在XML中定义 * * @param source {@link InputSource} * @return XML文档对象 * @since 3.0.9 */ public static Document readXML(InputSource source) { final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { final DocumentBuilder builder = dbf.newDocumentBuilder(); return builder.parse(source); } catch (Exception e) { throw new UtilException(e, "Parse XML from stream error!"); } } /** * 将String类型的XML转换为XML文档 * * @param xmlStr XML字符串 * @return XML文档 */ public static Document parseXml(String xmlStr) { if (StrUtil.isBlank(xmlStr)) { throw new IllegalArgumentException("XML content string is empty !"); } xmlStr = cleanInvalid(xmlStr); return readXML(new InputSource(StrUtil.getReader(xmlStr))); } /** * 从XML中读取对象 * Reads serialized object from the XML file. * @param 对象类型 * @param source XML文件 * @return 对象 * @throws IOException IO异常 */ public static T readObjectFromXml(File source) throws IOException { return readObjectFromXml(new InputSource(FileUtil.getInputStream(source))); } /** * 从XML中读取对象 * Reads serialized object from the XML file. * * @param 对象类型 * @param xmlStr XML内容 * @return 对象 * @throws IOException IO异常 * @since 3.2.0 */ public static T readObjectFromXml(String xmlStr) throws IOException { return readObjectFromXml(new InputSource(StrUtil.getReader(xmlStr))); } /** * 从XML中读取对象 * Reads serialized object from the XML file. * * @param 对象类型 * @param source {@link InputSource} * @return 对象 * @throws IOException IO异常 * @since 3.2.0 */ @SuppressWarnings("unchecked") public static T readObjectFromXml(InputSource source) throws IOException { Object result = null; XMLDecoder xmldec = null; try { xmldec = new XMLDecoder(source); result = xmldec.readObject(); } finally { IoUtil.close(xmldec); } return (T) result; } // -------------------------------------------------------------------------------------- Write /** * 将XML文档转换为String
* 字符编码使用XML文档中的编码,获取不到则使用UTF-8 * * @param doc XML文档 * @return XML字符串 */ public static String toStr(Document doc) { return toStr(doc, null); } /** * 将XML文档转换为String
* 此方法会修改Document中的字符集 * * @param doc XML文档 * @param charset 自定义XML文件的编码,如果为{@code null} 读取XML文档中的编码,否则默认UTF-8 * @return XML字符串 */ public static String toStr(Document doc, String charset) { return toStr(doc, charset, true); } /** * 将XML文档转换为String
* 此方法会修改Document中的字符集 * * @param doc XML文档 * @param charset 自定义XML文件的编码,如果为{@code null} 读取XML文档中的编码,否则默认UTF-8 * @param isPretty 是否格式化输出 * @return XML字符串 * @since 3.0.9 */ public static String toStr(Document doc, String charset, boolean isPretty) { final StringWriter writer = StrUtil.getWriter(); try { write(doc, writer, isPretty); } catch (Exception e) { throw new UtilException(e, "Trans xml document to string error!"); } return writer.toString(); } /** * 将XML文档写入到文件
* 使用Document中的编码 * * @param doc XML文档 * @param absolutePath 文件绝对路径,不存在会自动创建 */ public static void toFile(Document doc, String absolutePath) { toFile(doc, absolutePath, null); } /** * 将XML文档写入到文件
* * @param doc XML文档 * @param path 文件路径绝对路径或相对ClassPath路径,不存在会自动创建 * @param charset 自定义XML文件的编码,如果为{@code null} 读取XML文档中的编码,否则默认UTF-8 */ public static void toFile(Document doc, String path, String charset) { if (StrUtil.isBlank(charset)) { charset = doc.getXmlEncoding(); } if (StrUtil.isBlank(charset)) { charset = CharsetUtil.UTF_8; } BufferedWriter writer = null; try { writer = FileUtil.getWriter(path, charset, false); write(doc, writer, true); } finally { IoUtil.close(writer); } } /** * 将XML文档写出 * @param doc {@link Document} XML文档 * @param writer 写出的Writer,Writer决定了输出XML的编码 * @param isPretty 是否格式化输出 * @since 3.0.9 */ public static void write(Document doc, Writer writer, boolean isPretty) { final TransformerFactory factory = TransformerFactory.newInstance(); try { final Transformer xformer = factory.newTransformer(); xformer.setOutputProperty(OutputKeys.INDENT, isPretty ? "yes" : "no"); xformer.transform(new DOMSource(doc), new StreamResult(writer)); } catch (Exception e) { throw new UtilException("Trans xml document to string error!", e); } } // -------------------------------------------------------------------------------------- Create /** * 创建XML文档
* 创建的XML默认是utf8编码,修改编码的过程是在toStr和toFile方法里,既XML在转为文本的时候才定义编码 * * @param rootElementName 根节点名称 * @return XML文档 */ public static Document createXml(String rootElementName) { final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; try { builder = dbf.newDocumentBuilder(); } catch (Exception e) { throw new UtilException("Create xml document error!", e); } final Document doc = builder.newDocument(); doc.appendChild(doc.createElement(rootElementName)); return doc; } // -------------------------------------------------------------------------------------- Function /** * 获得XML文档根节点 * @param doc {@link Document} * @return 根节点 * @see Document#getDocumentElement() * @since 3.0.8 */ public static Element getRootElement(Document doc) { return (null == doc) ? null : doc.getDocumentElement(); } /** * 去除XML文本中的无效字符 * * @param xmlContent XML文本 * @return 当传入为null时返回null */ public static String cleanInvalid(String xmlContent) { if (xmlContent == null) { return null; } return xmlContent.replaceAll(INVALID_REGEX, ""); } /** * 根据节点名获得子节点列表 * * @param element 节点 * @param tagName 节点名,如果节点名为空(null或blank),返回所有子节点 * @return 节点列表 */ public static List getElements(Element element, String tagName) { final NodeList nodeList = StrUtil.isBlank(tagName) ? element.getChildNodes() : element.getElementsByTagName(tagName); return transElements(element, nodeList); } /** * 根据节点名获得第一个子节点 * * @param element 节点 * @param tagName 节点名 * @return 节点 */ public static Element getElement(Element element, String tagName) { final NodeList nodeList = element.getElementsByTagName(tagName); if (nodeList == null || nodeList.getLength() < 1) { return null; } int length = nodeList.getLength(); for (int i = 0; i < length; i++) { Element childEle = (Element) nodeList.item(i); if (childEle == null || childEle.getParentNode() == element) { return childEle; } } return null; } /** * 根据节点名获得第一个子节点 * * @param element 节点 * @param tagName 节点名 * @return 节点中的值 */ public static String elementText(Element element, String tagName) { Element child = getElement(element, tagName); return child == null ? null : child.getTextContent(); } /** * 根据节点名获得第一个子节点 * * @param element 节点 * @param tagName 节点名 * @param defaultValue 默认值 * @return 节点中的值 */ public static String elementText(Element element, String tagName, String defaultValue) { Element child = getElement(element, tagName); return child == null ? defaultValue : child.getTextContent(); } /** * 将NodeList转换为Element列表 * * @param nodeList NodeList * @return Element列表 */ public static List transElements(NodeList nodeList) { return transElements(null, nodeList); } /** * 将NodeList转换为Element列表
* 非Element节点将被忽略 * * @param parentEle 父节点,如果指定将返回此节点的所有直接子节点,nul返回所有就节点 * @param nodeList NodeList * @return Element列表 */ public static List transElements(Element parentEle, NodeList nodeList) { int length = nodeList.getLength(); final ArrayList elements = new ArrayList(length); Node node; Element element; for (int i = 0; i < length; i++) { node = nodeList.item(i); if(Node.ELEMENT_NODE == node.getNodeType()) { element = (Element) nodeList.item(i); if (parentEle == null || element.getParentNode() == parentEle) { elements.add(element); } } } return elements; } /** * 将可序列化的对象转换为XML写入文件,已经存在的文件将被覆盖
* Writes serializable object to a XML file. Existing file will be overwritten * @param 对象类型 * @param dest 目标文件 * @param t 对象 * @throws IOException IO异常 */ public static void writeObjectAsXml(File dest, T t) throws IOException { XMLEncoder xmlenc = null; try { xmlenc = new XMLEncoder(FileUtil.getOutputStream(dest)); xmlenc.writeObject(t); } finally { //关闭XMLEncoder会相应关闭OutputStream IoUtil.close(xmlenc); } } /** * 创建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节点等 * @param returnType 返回类型,{@link javax.xml.xpath.XPathConstants} * @return 匹配返回类型的值 * @since 3.2.0 */ public static Object getByXPath(String expression, Object source, QName returnType) { final XPath xPath = createXPath(); try { if(source instanceof InputSource) { return xPath.evaluate(expression, (InputSource)source, returnType); }else { return xPath.evaluate(expression, source, returnType); } } catch (XPathExpressionException e) { throw new UtilException(e); } } // ---------------------------------------------------------------------------------------- Private method start // ---------------------------------------------------------------------------------------- Private method end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy