private void toXML(BaseComponent root, Node parent) {
        TreeMap<String, String> properties = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        Class<?> clazz = root.getClass();
        ComponentDefinition def = root.getDefinition();
        String cmpname = def.getTag();

        if (def.getComponentClass() != clazz) {
            properties.put("impl", clazz.getName());
        }

        Node child = doc.createElement(cmpname);
        parent.appendChild(child);

        for (PropertyDescriptor propDx : PropertyUtils.getPropertyDescriptors(root)) {
            Method getter = propDx.getReadMethod();
            Method setter = propDx.getWriteMethod();
            String name = propDx.getName();

            if (getter != null && setter != null && !isExcluded(name, cmpname, null)
                    && !setter.isAnnotationPresent(Deprecated.class)
                    && (getter.getReturnType() == String.class || getter.getReturnType().isPrimitive())) {
                try {
                    Object raw = getter.invoke(root);
                    String value = raw == null ? null : raw.toString();

                    if (StringUtils.isEmpty(value) || ("id".equals(name) && value.startsWith("z_"))
                            || isExcluded(name, cmpname, value)) {
                        continue;
                    }

                    properties.put(name, value.toString());
                } catch (Exception e) {}
            }
        }

        for (Entry<String, String> entry : properties.entrySet()) {
            Attr attr = doc.createAttribute(entry.getKey());
            child.getAttributes().setNamedItem(attr);
            attr.setValue(entry.getValue());
        }

        properties = null;

        for (BaseComponent cmp : root.getChildren()) {
            toXML(cmp, child);
        }
    }
private void toXML ( BaseComponent root , Node parent ) { TreeMap < String , String > properties = new TreeMap < > ( String . CASE_INSENSITIVE_ORDER ) ; Class < ? > clazz = root . getClass ( ) ; ComponentDefinition def = root . getDefinition ( ) ; String cmpname = def . getTag ( ) ; if ( def . getComponentClass ( ) != clazz ) { properties . put ( "impl" , clazz . getName ( ) ) ; } Node child = doc . createElement ( cmpname ) ; parent . appendChild ( child ) ; for ( PropertyDescriptor propDx : PropertyUtils . getPropertyDescriptors ( root ) ) { Method getter = propDx . getReadMethod ( ) ; Method setter = propDx . getWriteMethod ( ) ; String name = propDx . getName ( ) ; if ( getter != null && setter != null && ! isExcluded ( name , cmpname , null ) && ! setter . isAnnotationPresent ( Deprecated . class ) && ( getter . getReturnType ( ) == String . class || getter . getReturnType ( ) . isPrimitive ( ) ) ) { try { Object raw = getter . invoke ( root ) ; String value = raw == null ? null : raw . toString ( ) ; if ( StringUtils . isEmpty ( value ) || ( "id" . equals ( name ) && value . startsWith ( "z_" ) ) || isExcluded ( name , cmpname , value ) ) { continue ; } properties . put ( name , value . toString ( ) ) ; } catch ( Exception e ) { } } } for ( Entry < String , String > entry : properties . entrySet ( ) ) { Attr attr = doc . createAttribute ( entry . getKey ( ) ) ; child . getAttributes ( ) . setNamedItem ( attr ) ; attr . setValue ( entry . getValue ( ) ) ; } properties = null ; for ( BaseComponent cmp : root . getChildren ( ) ) { toXML ( cmp , child ) ; } }
Adds the root component to the XML document at the current level along with all bean
properties that return String or primitive types. Then, recurses over all of the root
component's children.

@param root The root component.
@param parent The parent XML node.