com.jianggujin.http.util.JXMLUtils Maven / Gradle / Ivy
The newest version!
/**
* Copyright 2018 jianggujin (www.jianggujin.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jianggujin.http.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* XML工具,禁用实体解析
*
* @author jianggujin
*
*/
public class JXMLUtils {
public final static String FRATURE_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
public final static String FRATURE_EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
public final static String FRATURE_EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
public final static String FRATURE_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
public final static String SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
public static DocumentBuilderFactory newDocumentBuilderFactory() throws ParserConfigurationException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setFeature(FRATURE_DISALLOW_DOCTYPE_DECL, true);
documentBuilderFactory.setFeature(FRATURE_EXTERNAL_GENERAL_ENTITIES, false);
documentBuilderFactory.setFeature(FRATURE_EXTERNAL_PARAMETER_ENTITIES, false);
documentBuilderFactory.setFeature(FRATURE_LOAD_EXTERNAL_DTD, false);
// documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,
// true);
documentBuilderFactory.setXIncludeAware(false);
documentBuilderFactory.setExpandEntityReferences(false);
return documentBuilderFactory;
}
public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
return newDocumentBuilderFactory().newDocumentBuilder();
}
public static Document newDocument() throws ParserConfigurationException {
return newDocumentBuilder().newDocument();
}
public static SAXParserFactory newSAXParserFactory() throws ParserConfigurationException, SAXException {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setFeature(FRATURE_EXTERNAL_GENERAL_ENTITIES, false);
saxParserFactory.setFeature(FRATURE_EXTERNAL_PARAMETER_ENTITIES, false);
saxParserFactory.setFeature(FRATURE_LOAD_EXTERNAL_DTD, false);
return saxParserFactory;
}
/**
* SAX
*
* @return
* @throws ParserConfigurationException
* @throws SAXException
*/
public static SAXParser newSAXParser() throws ParserConfigurationException, SAXException {
return newSAXParserFactory().newSAXParser();
}
/**
* SAX2
*
* @return
* @throws SAXException
*/
public static XMLReader newXMLReader() throws SAXException {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature(FRATURE_DISALLOW_DOCTYPE_DECL, true);
// This may not be strictly required as DTDs shouldn't be allowed at all,
// per previous line.
reader.setFeature(FRATURE_LOAD_EXTERNAL_DTD, false);
reader.setFeature(FRATURE_EXTERNAL_GENERAL_ENTITIES, false);
reader.setFeature(FRATURE_EXTERNAL_PARAMETER_ENTITIES, false);
return reader;
}
public static TransformerFactory newTransformerFactory() {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
return transformerFactory;
}
public static XMLInputFactory newXMLInputFactory() {
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
// This disables DTDs entirely for that factory
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
// disable external entities
xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
return xmlInputFactory;
}
public static Validator newValidator() throws SAXException {
SchemaFactory schemaFactory = SchemaFactory.newInstance(SCHEMA_LANGUAGE);
Schema schema = schemaFactory.newSchema();
Validator validator = schema.newValidator();
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
return validator;
}
public static SchemaFactory newSchemaFactory() throws SAXException {
SchemaFactory schemaFactory = SchemaFactory.newInstance(SCHEMA_LANGUAGE);
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
return schemaFactory;
}
public static SAXTransformerFactory newSAXTransformerFactory() throws SAXException {
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
return sf;
}
public static T unmarshal(Class classesToBeBound, InputSource source)
throws ParserConfigurationException, SAXException, JAXBException {
SAXParserFactory saxParserFactory = newSAXParserFactory();
Source xmlSource = new SAXSource(saxParserFactory.newSAXParser().getXMLReader(), source);
return unmarshal(classesToBeBound, xmlSource);
}
@SuppressWarnings("unchecked")
public static T unmarshal(Class classesToBeBound, Source source) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(classesToBeBound);
Unmarshaller um = jc.createUnmarshaller();
return (T) um.unmarshal(source);
}
/**
* 创建XML文档
*
* @param transformerFactory
* @param map
* @param root
* @param streamResult
* @param properties
* @throws ParserConfigurationException
* @throws TransformerException
* @throws SAXException
* @see OutputKeys
*/
public static void create(TransformerFactory transformerFactory, Map map, String root,
StreamResult streamResult, String... properties)
throws ParserConfigurationException, TransformerException, SAXException {
if (transformerFactory instanceof SAXTransformerFactory) {
SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory) transformerFactory;
TransformerHandler transformerHandler = saxTransformerFactory.newTransformerHandler();
Transformer transformer = transformerHandler.getTransformer();
setOutputProperty(transformer, properties);
transformerHandler.setResult(streamResult);
transformerHandler.startDocument();
transformerHandler.startElement(null, null, root, null);
for (Entry entry : map.entrySet()) {
String key = entry.getKey(), value = entry.getValue();
transformerHandler.startElement(null, null, key, null);
if (!JDataUtils.isEmpty(value)) {
char[] characters = value.toCharArray();
transformerHandler.characters(characters, 0, characters.length);
}
transformerHandler.endElement(null, null, key);
}
transformerHandler.endElement(null, null, root);
transformerHandler.endDocument();
} else {
Document document = newDocument();
document.setXmlStandalone(true);
Element rootNode = document.createElement(root);
for (Entry entry : map.entrySet()) {
String key = entry.getKey(), value = entry.getValue();
Element node = document.createElement(key);
if (!JDataUtils.isEmpty(value)) {
node.setTextContent(value);
}
rootNode.appendChild(node);
}
document.appendChild(rootNode);
Transformer transformer = transformerFactory.newTransformer();
Source source = new DOMSource(document);
setOutputProperty(transformer, properties);
transformer.transform(source, streamResult);
}
}
/**
* 创建XML文档
*
* @param transformerFactory
* @param element
* @param streamResult
* @param properties
* @throws ParserConfigurationException
* @throws TransformerException
* @throws SAXException
* @see OutputKeys
*/
public static void create(TransformerFactory transformerFactory, JElement element, StreamResult streamResult,
String... properties) throws ParserConfigurationException, TransformerException, SAXException {
if (transformerFactory instanceof SAXTransformerFactory) {
SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory) transformerFactory;
TransformerHandler transformerHandler = saxTransformerFactory.newTransformerHandler();
Transformer transformer = transformerHandler.getTransformer();
setOutputProperty(transformer, properties);
transformerHandler.setResult(streamResult);
transformerHandler.startDocument();
create(element, transformerHandler);
transformerHandler.endDocument();
} else {
Document document = newDocument();
document.setXmlStandalone(true);
document.appendChild(create(element, document));
Transformer transformer = transformerFactory.newTransformer();
Source source = new DOMSource(document);
setOutputProperty(transformer, properties);
transformer.transform(source, streamResult);
}
}
private static void setOutputProperty(Transformer transformer, String... properties) {
int len = properties.length;
if (len > 0 && len % 2 == 0) {
for (int i = 0; i < len; i++) {
transformer.setOutputProperty(properties[i], properties[++i]);
}
}
}
private static void create(JElement element, TransformerHandler transformerHandler) throws SAXException {
AttributesImpl atts = new AttributesImpl();
Collection attributes = element.getAttributes();
if (attributes != null) {
for (JAttribute attribute : attributes) {
atts.addAttribute(attribute.getUri(), attribute.getLocalName(), attribute.getQName(),
attribute.getType(), attribute.getValue());
}
}
transformerHandler.startElement(element.getUri(), element.getLocalName(), element.getQName(), atts);
List childrens = element.getChildrens();
if (childrens != null) {
for (JElement children : childrens) {
create(children, transformerHandler);
}
}
String text = element.getText();
if (!JDataUtils.isEmpty(text)) {
char[] characters = text.toCharArray();
transformerHandler.characters(characters, 0, characters.length);
}
transformerHandler.endElement(element.getUri(), element.getLocalName(), element.getQName());
}
private static Element create(JElement element, Document document) throws ParserConfigurationException {
Element node = document.createElement(element.qName);
if (!JDataUtils.isEmpty(element.text)) {
node.setTextContent(element.text);
}
Collection attributes = element.getAttributes();
if (attributes != null) {
for (JAttribute attribute : attributes) {
node.setAttribute(attribute.getQName(), attribute.getValue());
}
}
List childrens = element.getChildrens();
if (childrens != null) {
for (JElement children : childrens) {
node.appendChild(create(children, document));
}
}
return node;
}
/**
* 解析
*
* @param source
* @param xmlHandler
* @return
* @throws IOException
* @throws SAXException
*/
public static T parse(InputSource source, JXmlHandler xmlHandler) throws IOException, SAXException {
return parse(newXMLReader(), source, xmlHandler);
}
/**
* 解析
*
* @param reader
* @param source
* @param xmlHandler
* @return
* @throws IOException
* @throws SAXException
*/
public static T parse(XMLReader reader, InputSource source, JXmlHandler xmlHandler)
throws IOException, SAXException {
reader.setContentHandler(xmlHandler);
reader.setEntityResolver(xmlHandler);
reader.setErrorHandler(xmlHandler);
reader.setDTDHandler(xmlHandler);
reader.parse(source);
return xmlHandler.getData();
}
/**
* 将Element子元素解析成Map
*
* @param element
* @return
* @throws IOException
* @throws SAXException
*/
public static Map parse(Element element) throws IOException, SAXException {
NodeList nodeList = element.getChildNodes();
Map map = new HashMap();
int len;
if (nodeList != null && (len = nodeList.getLength()) > 0) {
for (int i = 0; i < len; i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element child = (Element) node;
map.put(child.getNodeName(), child.getTextContent());
}
}
}
return map;
}
public static class JElement {
private String uri;
private String localName;
private String qName;
private Map attributes;
private String text;
private JElement parent;
private List childrens;
public JElement() {
}
public JElement(String qName) {
this.qName = qName;
}
public JElement(String qName, String text) {
this.qName = qName;
this.text = text;
}
public String getUri() {
return uri;
}
public JElement setUri(String uri) {
this.uri = uri;
return this;
}
public String getLocalName() {
return localName;
}
public JElement setLocalName(String localName) {
this.localName = localName;
return this;
}
public String getQName() {
return qName;
}
public JElement setQName(String qName) {
this.qName = qName;
return this;
}
public Collection getAttributes() {
return attributes == null ? null : attributes.values();
}
public JElement setAttributes(String qName, String value) {
return setAttributes(new JAttribute(qName, value));
}
public JElement setAttributes(JAttribute attribute) {
if (attributes == null) {
synchronized (this) {
if (attributes == null) {
attributes = new LinkedHashMap();
}
}
}
this.attributes.put(attribute.getQName(), attribute);
return this;
}
public String getText() {
return text;
}
public JElement setText(String text) {
this.text = text;
return this;
}
public JElement getParent() {
return parent;
}
private JElement setParent(JElement parent) {
this.parent = parent;
return this;
}
public List getChildrens() {
return childrens;
}
public JElement appendChildren(String qName, String text) {
return appendChildren(new JElement(qName, text));
}
public JElement appendChildren(JElement children) {
if (childrens == null) {
synchronized (this) {
if (childrens == null) {
childrens = new ArrayList();
}
}
}
children.setParent(this);
this.childrens.add(children);
return this;
}
@Override
public String toString() {
return "[uri=" + uri + ", localName=" + localName + ", qName=" + qName + ", attributes=" + attributes
+ ", text=" + text + ", childrens=" + childrens + "]";
}
}
public static class JAttribute {
private String uri;;
public String localName;
public String qName;
public String type;
public String value;
public JAttribute() {
}
public JAttribute(String qName) {
this.qName = qName;
}
public JAttribute(String qName, String value) {
this.qName = qName;
this.value = value;
}
public String getUri() {
return uri;
}
public JAttribute setUri(String uri) {
this.uri = uri;
return this;
}
public String getLocalName() {
return localName;
}
public JAttribute setLocalName(String localName) {
this.localName = localName;
return this;
}
public String getQName() {
return qName;
}
public JAttribute setQName(String qName) {
this.qName = qName;
return this;
}
public String getType() {
return type;
}
public JAttribute setType(String type) {
this.type = type;
return this;
}
public String getValue() {
return value;
}
public JAttribute setValue(String value) {
this.value = value;
return this;
}
@Override
public String toString() {
return "[url=" + uri + ", localName=" + localName + ", qName=" + qName + ", value=" + value + "]";
}
}
public static interface JXmlHandler extends ContentHandler, EntityResolver, ErrorHandler, DTDHandler {
T getData();
}
public static class JElementXmlHandler extends DefaultHandler implements JXmlHandler {
private JElement root;
private LinkedList stack = new LinkedList();
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
int len = attributes.getLength();
JElement element = new JElement();
if (root == null) {
root = element;
}
element.uri = uri;
element.localName = localName;
element.qName = qName;
if (len > 0) {
for (int i = 0; i < len; i++) {
JAttribute attribute = new JAttribute();
attribute.uri = attributes.getURI(i);
attribute.localName = attributes.getLocalName(i);
attribute.qName = attributes.getQName(i);
attribute.type = attributes.getType(i);
attribute.value = attributes.getValue(i);
element.setAttributes(attribute);
}
}
JElement parent = stack.peek();
if (parent != null) {
parent.appendChildren(element);
}
stack.push(element);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
stack.peek().text = new String(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
JElement element = stack.peek();
if (JDataUtils.equals(uri, element.uri) && JDataUtils.equals(localName, element.localName)
&& JDataUtils.equals(qName, element.qName)) {
stack.pop();
}
}
@Override
public JElement getData() {
return this.root;
}
}
public static class JMapXmlHandler extends DefaultHandler implements JXmlHandler
© 2015 - 2025 Weber Informatics LLC | Privacy Policy