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

com.crabshue.commons.xml.XmlPrintUtils Maven / Gradle / Ivy

package com.crabshue.commons.xml;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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 org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;

import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.xml.exceptions.XmlErrorType;
import com.crabshue.commons.xml.inputsource.InputSourceBuilder;
import com.crabshue.commons.xml.processinginstructions.ProcessingInstructionsConstants;
import lombok.Data;
import lombok.NonNull;

/**
 * Utility class for printing XML documents.
 *
 */
public class XmlPrintUtils {

    /**
     * Converts a DOM document, into a set of string lines, preserving or not the XML declaration processing instruction.
     *
     * @param doc the source document to convert
     * @return the string collection representation of a document.
     */
    public static Collection stringify(@NonNull final Document doc) {

        return stringify(doc, Options.defaultOptions());
    }

    /**
     * Converts a DOM document, into a set of string lines, preserving or not the XML declaration processing instruction.
     *
     * @param doc     the source document to convert
     * @param options
     * @return the string collection representation of a document.
     */
    public static Collection stringify(@NonNull final Document doc,
                                               @NonNull final XmlPrintUtils.Options options) {

        StringWriter sw = new StringWriter();

        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, options.isOmitXmlDeclaration() ? "yes" : "no");
            transformer.setOutputProperty(OutputKeys.METHOD, options.getOutputMethod());
            transformer.setOutputProperty(OutputKeys.INDENT, options.isIndent() ? "yes" : "no");
            transformer.setOutputProperty(OutputKeys.ENCODING, options.getEncoding());
            transformer.transform(new DOMSource(doc), new StreamResult(sw));
        } catch (Exception ex) {
            throw new SystemException(XmlErrorType.ERROR_MODIFYING_XML, "Error converting to String", ex);
        }

        Collection lines = Arrays.asList(StringUtils.split(sw.toString(), "\n"));
        return XmlPrintUtils.isolateProcessingInstructions(lines);
    }

    /**
     * Prettify a collection of {@link String lines} (representing an XML).
     *
     * @param lines the collection of lines.
     * @return the prettified lines.
     */
    public static Collection prettyPrint(@NonNull final Collection lines) {

        Collection ret;
        final Document document = XmlDocumentBuilder.of(InputSourceBuilder.newInputSource(lines)).build();

        ret = XmlPrintUtils.stringify(document, new Options().setOmitXmlDeclaration(false));
        ret = isolateProcessingInstructions(ret);
        return ret;
    }

    /**
     * Modify a set of {@link String lines}, to put the xml processing instructions on individual lines.
     *
     * @param lines the lines.
     * @return the prettified lines.
     */
    public static Collection isolateProcessingInstructions(@NonNull final Collection lines) {

        Collection ret = new ArrayList<>();

        Pattern pattern = Pattern.compile(ProcessingInstructionsConstants.PROCESSING_INSTRUCTION_REGEXP);
        for (String line : lines) {
            Matcher matcher = pattern.matcher(line);
            if (matcher.find()) {
                String s = line.replaceAll(ProcessingInstructionsConstants.PROCESSING_INSTRUCTION_REGEXP, "\n$0\n");
                ret.addAll(Arrays.asList(StringUtils.split(s, "\n")));
            } else {
                ret.add(line);
            }

        }
        return ret;
    }

    /**
     * Stringify options
     */
    @Data
    public static class Options {

        private boolean omitXmlDeclaration = false;
        private String outputMethod = "xml";
        private String encoding = "UTF-8";
        private boolean indent = true;

        public static Options defaultOptions() {
            return new Options();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy