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

org.ioc.commons.utils.XMLUtil Maven / Gradle / Ivy

package org.ioc.commons.utils;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Class for parsing a XML to a bean and vice versa.
 * 
 * Instructions for using xml2bean:
 * 
 * Create a bean having attributes with the same name of the tags and generate
 * getters & setters of it.
 * 
 * An XML like:
 * 
 * 
 * {@code
 * 
 * 	
 * 		FOO1
 * 		bar1
 * 		baz1
 * 	
 * 	
 * 		FOO2
 * 		bar2
 * 		baz2
 * 	
 * 
 * }
 * 
* * will require two beans like this: * *
 * {@code
 * 	public class Workareas {
 * 	private List workareas = new ArrayList();
 * 
 * 	public List getWorkareas() {
 * 		return workareas;
 * 	}
 * 
 * 	public void setWorkareas(List workareas) {
 * 		this.workareas = workareas;
 * 	}
 * }
 * 
 * public class Workarea {
 * 	private WorkareaType type;
 * 	private String id;
 * 	private String name;
 * 	
 * 	// Getters & Setters of attributes
 * }
 * 
 * public enum WorkareaType {
 * 	FOO1, FOO2;
 * }
 * }
 * 
* * @author Jesús Lunar Pérez */ public class XMLUtil { /** * Logger for this class */ private static final FormatterLogger logger = FormatterLogger.getLogger(XMLUtil.class); public static class XMLUtilException extends Exception { /** * Serial number */ private static final long serialVersionUID = 5118145977808353316L; public XMLUtilException(String message) { super(message); } public XMLUtilException(String message, Throwable cause) { super(message, cause); } } private XMLUtil() { // Static use only } private static String dateTimeFormat = "dd/MM/yyyy HH:mm:ss"; private static String dateFormat = "dd/MM/yyyy"; private static NumberFormat numberFormat = null; public static interface XMLNewBeanFactory { public Object getNewInstance(String nombreTag, String defaultPackageName); } public static interface XMLProcessingVisitor { String visit(String nodeText, Class parameterType); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public static @interface XMLUtilTagName { String value(); } /** * Used to mark bean fields which we want to convert them into XML * attributes instead of child nodes. * * ONLY valid for primtive types. * * @author Jesús Lunar Pérez * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public static @interface Attribute { } public static void xml2Bean(Element tag, Object bean, boolean log) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { xml2Bean(tag, bean, log, (XMLProcessingVisitor) null); } public static void xml2Bean(Element tag, Object bean, boolean log, XMLProcessingVisitor xmlCalcOperationOnProcessingVisitor) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, SecurityException, NoSuchFieldException, XMLUtilException { xml2Bean(tag, bean, log, (XMLNewBeanFactory) null, xmlCalcOperationOnProcessingVisitor); } public static void xml2Bean(Element tag, Object bean, boolean log, XMLNewBeanFactory newBeanFactory) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { xml2Bean(tag, bean, log, newBeanFactory, null); } public static void xml2Bean(Element tag, Object bean, boolean log, XMLNewBeanFactory newBeanFactory, XMLProcessingVisitor xmlCalcOperationOnProcessingVisitor) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { StringBuffer logb = new StringBuffer(); xml2Bean(tag, bean, log, logb, newBeanFactory, xmlCalcOperationOnProcessingVisitor); if (log) { logger.info(logb.toString()); } } public static void xml2Bean(Element tag, Object bean, int level, Package parentPackage, boolean log) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { xml2Bean(tag, bean, 1, parentPackage, log, null); } public static void xml2Bean(Element tag, Object bean, int level, Package parentPackage, boolean log, XMLNewBeanFactory newBeanFactory) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { StringBuffer logb = new StringBuffer(); xml2Bean(tag, bean, level, parentPackage, log, logb, newBeanFactory, null); if (log) { logger.info(logb.toString()); } } protected static void xml2Bean(Element tag, Object bean, boolean log, StringBuffer logb, XMLNewBeanFactory newBeanFactory) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { xml2Bean(tag, bean, log, logb, newBeanFactory, (XMLProcessingVisitor) null); } protected static void xml2Bean(Element tag, Object bean, boolean log, StringBuffer logb, XMLNewBeanFactory newBeanFactory, XMLProcessingVisitor xmlCalcOperationOnProcessingVisitor) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { xml2Bean(tag, bean, 1, bean.getClass().getPackage(), log, logb, newBeanFactory, xmlCalcOperationOnProcessingVisitor); } @SuppressWarnings("unchecked") protected static void xml2Bean(Element tag, Object bean, int level, Package parentPackage, boolean log, StringBuffer logb, XMLNewBeanFactory newBeanFactory, XMLProcessingVisitor processingVisitor) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { StringBuffer tabs = new StringBuffer(); for (int n = 0; n < level; n++) { tabs.append("\t"); } boolean isList = bean instanceof List; NodeList tagChildList = tag.getChildNodes(); if (log) { logb.append( tabs + "<" + tag.getTagName() + "> " + (isList ? "(list)" : "(bean) children=" + tagChildList.getLength())).append('\n'); } /** * Rellenamos los atributos */ NamedNodeMap attributes = tag.getAttributes(); setAttributes(bean, attributes, level, log, logb, processingVisitor); if (!isList) { /** * Rellenamos los tags hijo */ setTagChildren(bean, tagChildList, level, parentPackage, log, logb, newBeanFactory, processingVisitor); } else { List lista = (List) bean; int length = tagChildList.getLength(); if (length > 0) { for (int i = 0; i < length; i++) { Node nodoHijo = tagChildList.item(i); if (nodoHijo instanceof Element) { Element tagHijo = (Element) nodoHijo; if (parentPackage == null) { String txt = tagHijo.getTextContent(); lista.add(txt); if (log) { logb.append(tabs + "\t" + txt).append('\n'); } } else { String nombreTag = tagHijo.getTagName(); Class superClass = bean.getClass(); Type type = superClass.getGenericSuperclass(); Type[] typeArguments = null; while (typeArguments == null && (superClass = superClass.getSuperclass()) != null) { if ((type instanceof ParameterizedType)) { typeArguments = ((ParameterizedType) type).getActualTypeArguments(); } } String packageName = null; if (typeArguments != null) { /** * In a list we only have a unique parameter * type */ Type typeArgument = typeArguments[0]; if (typeArgument instanceof Class) { packageName = ((Class) typeArgument).getPackage().getName(); } } if (packageName == null) { packageName = parentPackage.getName(); } String className = packageName + "." + capitalize(nombreTag); Object newInstance = getInstance(nombreTag, className, packageName, newBeanFactory); xml2Bean(tagHijo, newInstance, log, logb, newBeanFactory, processingVisitor); lista.add(newInstance); } } } } else { String tagName = tag.getTagName(); throw new XMLUtilException(String.format( "The tag <%s> is related to a List thus it must necessarily contain children elements.", tagName)); } } } protected static Object getInstance(String tagName, String className, String defaultPackageName, XMLNewBeanFactory factory) throws ClassNotFoundException, IllegalAccessException, XMLUtilException { Object newInstance = null; if (factory != null && (newInstance = factory.getNewInstance(tagName, defaultPackageName)) != null) { return newInstance; } Class childClass = Class.forName(className); try { newInstance = childClass.newInstance(); return newInstance; } catch (InstantiationException e) { throw new XMLUtilException( String.format( "Unable to get a new instance for class/interface %s. Initialize bean attributes by default or use the parameter %s at the call.", childClass, XMLNewBeanFactory.class.getSimpleName()), e); } } private static String capitalize(String string) { StringBuffer sb = new StringBuffer(string); if (string.length() != 0) { char ch = sb.charAt(0); if (ch >= 97 && ch <= 122) { ch -= 32; } sb.setCharAt(0, ch); } return sb.toString(); } protected static void setAttributes(Object bean, NamedNodeMap attributes, int nivel, boolean log, StringBuffer logb, XMLProcessingVisitor processingVisitor) throws XMLUtilException, IllegalAccessException, InvocationTargetException { for (int i = 0; i < attributes.getLength(); i++) { Node attribute = attributes.item(i); String property = attribute.getNodeName(); String value = attribute.getNodeValue(); Method[] methods = bean.getClass().getMethods(); /** * Setting the attribute */ for (Method metodo : methods) { String methodName = metodo.getName(); boolean esSetterPropiedad = methodName.equalsIgnoreCase("set" + property); boolean tieneUnArgumento = (metodo.getParameterTypes().length == 1); if (!esSetterPropiedad || !tieneUnArgumento) { continue; } Class parameterType = metodo.getParameterTypes()[0]; Object valorSetter = null; if (processingVisitor != null) { value = processingVisitor.visit(value, parameterType); } if (parameterType.equals(Double.class) || parameterType.equals(double.class)) { try { valorSetter = (numberFormat != null) ? numberFormat.parse(value) : Double.valueOf(value); } catch (NumberFormatException | ParseException e) { throw new XMLUtilException(Format.substitute( "Cannot parse value '{0}' of type '{1}' using number formatted given", value, parameterType), e); } } else if (parameterType.equals(Float.class) || parameterType.equals(float.class)) { try { valorSetter = (numberFormat != null) ? numberFormat.parse(value) : Float.valueOf(value); } catch (NumberFormatException | ParseException e) { throw new XMLUtilException(Format.substitute( "Cannot parse value '{0}' of type '{1}' using number formatted given", value, parameterType), e); } } else if (parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)) { valorSetter = Boolean.valueOf(value); } else if (parameterType.equals(Integer.class) || parameterType.equals(int.class)) { valorSetter = Integer.valueOf(value); } else if (parameterType.equals(String.class)) { valorSetter = value; } else { throw new XMLUtilException("An attribute cannot be loaded on method '" + methodName + "' because of it has an unknow type. Type: " + parameterType.getSimpleName()); } StringBuffer tabs = new StringBuffer(); for (int n = 0; n < nivel; n++) { tabs.append("\t"); } if (log) { logb.append(tabs + " " + property + "=" + valorSetter).append('\n'); } metodo.invoke(bean, valorSetter); break; } } } protected static void setTagChildren(Object bean, NodeList tagsHijo, int nivel, Package paquetePadre, boolean log, StringBuffer logb, XMLNewBeanFactory newBeanFactory, XMLProcessingVisitor processingVisitor) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, SecurityException, NoSuchFieldException { StringBuffer tabs = new StringBuffer(); for (int n = 0; n < nivel; n++) { tabs.append("\t"); } for (int i = 0; i < tagsHijo.getLength(); i++) { Node nodo = tagsHijo.item(i); if (nodo instanceof Element) { Element tagHijo = (Element) nodo; String propiedad = tagHijo.getNodeName(); String valorTextoTag = tagHijo.getTextContent(); Method[] metodos = bean.getClass().getMethods(); /** * Setting the tag text */ boolean setterFound = false; for (Method metodo : metodos) { boolean esSetterPropiedad = metodo.getName().equalsIgnoreCase("set" + propiedad); boolean tieneUnArgumento = (metodo.getParameterTypes().length == 1); if (!esSetterPropiedad || !tieneUnArgumento) { continue; } setterFound = true; Class parameterType = metodo.getParameterTypes()[0]; Object valorSetter = null; if (processingVisitor != null) { valorTextoTag = processingVisitor.visit(valorTextoTag, parameterType); } if (parameterType.equals(Double.class) || parameterType.equals(double.class)) { try { valorSetter = (numberFormat != null) ? numberFormat.parse(valorTextoTag) : Double .valueOf(valorTextoTag); } catch (ParseException e) { throw new XMLUtilException(Format.substitute( "Cannot parse value '{0}' of type '{1}' using number formatted given", valorTextoTag, parameterType), e); } if (log) { logb.append(tabs + " Double " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)) { valorSetter = Boolean.valueOf(valorTextoTag); if (log) { logb.append(tabs + " Boolean " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(Float.class) || parameterType.equals(float.class)) { try { valorSetter = (numberFormat != null) ? numberFormat.parse(valorTextoTag) : Float .valueOf(valorTextoTag); } catch (ParseException e) { throw new XMLUtilException(Format.substitute( "Cannot parse value '{0}' of type '{1}' using number formatted given", valorTextoTag, parameterType), e); } if (log) { logb.append(tabs + " Float " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(Long.class) || parameterType.equals(long.class)) { valorSetter = Long.valueOf(valorTextoTag); if (log) { logb.append(tabs + " Long " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(Integer.class) || parameterType.equals(int.class)) { valorSetter = Integer.valueOf(valorTextoTag); if (log) { logb.append(tabs + " Integer " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(Short.class) || parameterType.equals(short.class)) { valorSetter = Short.valueOf(valorTextoTag); if (log) { logb.append(tabs + " Short " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(Character.class) || parameterType.equals(char.class)) { valorSetter = Character.valueOf(valorTextoTag.charAt(0)); if (log) { logb.append(tabs + " Character " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(Byte.class) || parameterType.equals(byte.class)) { valorSetter = Byte.valueOf(valorTextoTag); if (log) { logb.append(tabs + " Byte " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.equals(String.class)) { valorSetter = valorTextoTag; if (log) { logb.append(tabs + " String " + propiedad + "=" + valorSetter).append('\n'); } } else if (parameterType.isAssignableFrom(List.class)) { if (log) { logb.append(tabs + " List " + propiedad + "= ...").append('\n'); } Type tipoGenerico = metodo.getGenericParameterTypes()[0]; if (tipoGenerico instanceof ParameterizedType && ((ParameterizedType) tipoGenerico).getActualTypeArguments()[0].equals(String.class)) { valorSetter = new ArrayList(); xml2Bean(tagHijo, valorSetter, nivel + 1, null, log, logb, newBeanFactory, processingVisitor); } else { if (tipoGenerico instanceof ParameterizedType) { Type typeArg = ((ParameterizedType) tipoGenerico).getActualTypeArguments()[0]; Class classArg = (Class) typeArg; paquetePadre = classArg.getPackage(); } valorSetter = new ArrayList(); xml2Bean(tagHijo, valorSetter, nivel + 1, paquetePadre, log, logb, newBeanFactory, processingVisitor); } } else if (Enum.class.isAssignableFrom(parameterType)) { Field f = parameterType.getDeclaredField(valorTextoTag); valorSetter = f.get(null); if (log) { logb.append(tabs + " Enum " + propiedad + "=" + valorSetter).append('\n'); } } else { if (log) { logb.append(tabs + " " + parameterType + " " + propiedad).append('\n'); } valorSetter = parameterType.newInstance(); xml2Bean(tagHijo, valorSetter, nivel + 1, paquetePadre, log, logb, newBeanFactory, processingVisitor); } metodo.invoke(bean, valorSetter); } if (!setterFound) { if (log) { logb.append(tabs + " Unable to find a setter for property '" + propiedad + "' inside the class " + bean.getClass()); } } } } } public static boolean indentXml(StringBuffer xmlStr) { logger.debug("indentXml(StringBuffer) - start"); //$NON-NLS-1$ try { DocumentBuilder newDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputSource is = new InputSource(); is.setCharacterStream(new StringReader(xmlStr.toString())); Document root = newDocumentBuilder.parse(is); StringWriter stringWriter = indentXml(root); if (stringWriter == null) { return false; } xmlStr.setLength(0); xmlStr.append(stringWriter.toString()); logger.debug("indentXml(StringBuffer) - end"); //$NON-NLS-1$ return true; } catch (SAXException e) { logger.warn(e, "Error trying to indent XML. Let's continue..."); } catch (IOException e) { logger.warn(e, "Error trying to indent XML. Let's continue..."); } catch (ParserConfigurationException e) { logger.warn(e, "Error trying to indent XML. Let's continue..."); } logger.debug("indentXml(StringBuffer) - end"); //$NON-NLS-1$ return false; } public static StringWriter indentXml(Document root) { try { // Write file DOMSource domsource = new DOMSource(root); StringWriter stringWriter = new StringWriter(1024); StreamResult output = new StreamResult(stringWriter); // new // Set up TransformerFactory transfabrik = TransformerFactory.newInstance(); Transformer sTransformer; sTransformer = transfabrik.newTransformer(); sTransformer.setOutputProperty(OutputKeys.INDENT, "yes"); sTransformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); sTransformer.transform(domsource, output); return stringWriter; } catch (TransformerConfigurationException e) { logger.warn(e, "Error trying to indent XML. Let's continue..."); return null; } catch (TransformerException e) { logger.warn(e, "Error trying to indent XML. Let's continue..."); return null; } } public static Document bean2xml(Object bean) throws IllegalArgumentException, UnsupportedEncodingException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, ParserConfigurationException, TransformerException { return bean2xml(bean, false); } public static Document bean2xml(Object bean, boolean dateWithTime) throws IllegalArgumentException, UnsupportedEncodingException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, ParserConfigurationException, TransformerException { DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); Document doc = docBuilder.newDocument(); bean2xml(bean, null, doc, dateWithTime, 0, new HashMap()); return doc; } public static byte[] bean2xml(boolean indent, Object bean, boolean salidaEnUTF8) throws IllegalArgumentException, UnsupportedEncodingException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, ParserConfigurationException, TransformerException { return bean2xml(indent, bean, salidaEnUTF8, false); } public static byte[] bean2xml(boolean indent, Object bean, boolean salidaEnUTF8, boolean dateWithTime) throws IllegalArgumentException, UnsupportedEncodingException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, ParserConfigurationException, TransformerException { Document doc = bean2xml(bean, dateWithTime); byte[] xmlString = DOM2String(doc, salidaEnUTF8, indent); return xmlString; } protected static Element bean2xml(Object bean, Element parent, Document doc, boolean dateWithTime, int deep, Map processedObjects) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, XMLUtilException, ClassNotFoundException, ParserConfigurationException { if (processedObjects != null) { /** * Si se ha mostrado a un nivel más profundo, se muestra otra vez. * Si no, se omite. */ if (processedObjects.containsKey(bean)) { int objectDeep = processedObjects.get(bean); if (deep > objectDeep) { return null; } } processedObjects.put(bean, deep); } Class clazz = bean.getClass(); String rootName = null; String clazzName = clazz.getName(); XMLUtilTagName tagNameAnnot = clazz.getAnnotation(XMLUtilTagName.class); if (tagNameAnnot != null) { rootName = tagNameAnnot.value(); } else { rootName = getSimpleClassName(clazzName); } try { Element root = doc.createElement(rootName); if (parent != null) { parent.appendChild(root); } else { doc.appendChild(root); } Method[] methods = clazz.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; String methodName = method.getName(); if ((methodName.startsWith("get") || methodName.startsWith("is")) && method.getParameterTypes().length == 0 && !methodName.equals("getClass")) { Object result = method.invoke(bean, (Object[]) null); String propertyName = methodName.startsWith("get") ? Format.decapitalize(methodName.replaceFirst( "get", "")) : Format.decapitalize(methodName.replaceFirst("is", "")); Element propertyTag = doc.createElement(propertyName); boolean likeAttribute = false; if (result != null) { if (result instanceof List) { List lstResult = (List) result; for (Iterator it = lstResult.iterator(); it.hasNext();) { Object hijo = it.next(); if (hijo != null) { if (!isBasicType(hijo)) { bean2xml(hijo, propertyTag, doc, dateWithTime, deep + 1, processedObjects); } else { Element tagElement = doc.createElement(hijo.getClass().getSimpleName()); Text txtNode = doc.createCDATASection(hijo.toString()); tagElement.appendChild(txtNode); propertyTag.appendChild(tagElement); } } } } else if (isBasicType(result)) { /** * On primitives, we check if they are marked as @Attribue */ likeAttribute = checkMarkedAsAttribute(clazz, propertyName); String string = (numberFormat != null && result instanceof Number) ? numberFormat .format(result) : result.toString(); Text txtNode = doc.createCDATASection(string); if (!likeAttribute) { propertyTag.appendChild(txtNode); } else { root.setAttribute(propertyName, string); } } else if (result.getClass().isArray()) { for (int j = 0; j < Array.getLength(result); j++) { Object child = Array.get(result, j); if (child != null) { if (!isBasicType(child)) { bean2xml(child, propertyTag, doc, dateWithTime, deep + 1, processedObjects); } else { Element tagElement = doc.createElement(child.getClass().getSimpleName()); Text txtNode = doc.createCDATASection(child.toString()); tagElement.appendChild(txtNode); propertyTag.appendChild(tagElement); } } } } else if (result instanceof Date) { SimpleDateFormat sdf = null; if (dateWithTime) { sdf = new SimpleDateFormat(dateTimeFormat); } else { sdf = new SimpleDateFormat(dateFormat); } String fechaStr = sdf.format((Date) result); Text txtNode = doc.createCDATASection(fechaStr); propertyTag.appendChild(txtNode); } else if (result instanceof Enum) { Text txtNode = doc.createCDATASection(result.toString()); propertyTag.appendChild(txtNode); } else { bean2xml(result, propertyTag, doc, dateWithTime, deep + 1, processedObjects); } } else { /** * Si un valor es nulo también deberiamos de tener en * cuanta si lo queremos como atributo o no. En caso de * ser atributo directamente no aparecerá como atributo * vacío (los tags si aparecen cuando están vacíos). */ likeAttribute = checkMarkedAsAttribute(clazz, propertyName); } if (!likeAttribute) { root.appendChild(propertyTag); } } } return root; } catch (DOMException e) { logger.error(e, "clazzName={0} ; simpleClassName={1}", clazzName, rootName); throw e; } } private static boolean checkMarkedAsAttribute(Class clase, String nombrePropiedad) { try { Field f = clase.getDeclaredField(nombrePropiedad); boolean markedAsAttribute = f.isAnnotationPresent(Attribute.class); return markedAsAttribute; } catch (SecurityException e) { /* * El campo como tal no existe (es sólo un getter) así que no puede * estar marcado. Se devuelve falso. */ return false; } catch (NoSuchFieldException e) { /* * El campo como tal no existe (es sólo un getter) así que no puede * estar marcado. Se devuelve falso. */ return false; } } protected static boolean isBasicType(Object obj) { return obj instanceof String || obj instanceof Integer || obj instanceof Long || obj instanceof Double || obj instanceof Boolean || obj instanceof Float || obj instanceof Byte; } protected static byte[] DOM2String(Document doc, boolean salidaEnUTF8, boolean indent) throws TransformerException, UnsupportedEncodingException { TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = null; transformer = transformerFactory.newTransformer(); if (indent) { transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); } Source source = new DOMSource(doc); StringWriter writer = new StringWriter(); Result result = new StreamResult(writer); transformer.transform(source, result); return salidaEnUTF8 ? writer.toString().getBytes("UTF-8") : writer.toString().getBytes(); } protected static String getSimpleClassName(String className) { int idx = className.lastIndexOf('.'); String simple = className.substring(idx + 1); idx = simple.indexOf('$'); if (idx >= 0) { simple = simple.replaceAll("\\$", "."); } return simple; } public static String getDateTimeFormat() { return dateTimeFormat; } public static void setDateTimeFormat(String dateTimeFormat) { XMLUtil.dateTimeFormat = dateTimeFormat; } public static String getDateFormat() { return dateFormat; } public static void setDateFormat(String dateFormat) { XMLUtil.dateFormat = dateFormat; } public static NumberFormat getNumberFormat() { return numberFormat; } public static void setNumberFormat(NumberFormat numberFormat) { XMLUtil.numberFormat = numberFormat; } }