简体   繁体   中英

What is the best way to create XML files in Java?

We are presently using dom4j to create XML files. However, I'm guessing there's something better now. If we are Java 1.6 or later, what is the best (fastest when running, simple to use) class(es) to use when writing out an XML file.

I do not need to build a DOM and then write the entire DOM. I just need something that will write out the elements/attributes as I pass them to the class.

thanks - dave

My 2 cents goes to java-xmlbuilder . Only for building though. It's hell a lot less complicated than JAXP .

I guess you know about StAX and the SAX framework.
Just mentioning them in case you haven't considered them.

http://docs.oracle.com/javase/tutorial/jaxp/stax/example.html#bnbgx

http://docs.oracle.com/javaee/1.4/tutorial/doc/JAXPXSLT5.html

如果您只想编写一个对创建元素、属性和其他文档组件具有精确控制权的 XML 文档,您可以使用 StAX API 中的XMLStreamWriter

Hope following code will help you

//example, BETTER THAN USE STRING_BUILDER, this class auto escape data
//this is usage example for simple xhtml
public static void main(String[] args) throws Exception {
    XMLWriter docWriter = 
    XMLWriter.create("html", html->{
        html.children(new String[]{"head","title"}, title->title.childText("My TITLE"));
        html.child("body", body->{
            body.attr("bgcolor", "red");

            body.child("div", div->{
                Map<String, String> userMap = new LinkedHashMap<String, String>();
                userMap.put("roll-no", "1");
                userMap.put("name", "Dharm");
                div.child(userMap);
            });
            body.child("div", div->{
                Map<String, String> userMap = new LinkedHashMap<String, String>();
                userMap.put("roll-no", "2");
                userMap.put("name", "Pruthvi & Rajan"); //see here '&'
                div.child(userMap);
            });
        });
    });

    //call docWriter.write() method depends on requirement

    //example 1:directly generate html string
    System.out.println(docWriter.toXMLString());

    /*
    //example 2:write html string into stream
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    docWriter.write(out);
    System.out.println(out.toString());
    */

    /*
    //example 3:write html string into file
    java.io.File file = java.io.File.createTempFile("Test", ".html");
    docWriter.write(file);
    java.awt.Desktop.getDesktop().open(file);
    */
}

I have created my custom class for that dynamic xml creation by code

package test.util.doc;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Map;
import java.util.function.Consumer;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
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.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;


/** XML/HTML document writer class<br/>
 * Internally uses w3c DOM <br/>
 * @see Document
 * @author Dharmendrasinh Chudasama
 */
public class XMLWriter {

    /**
     * @param rootElementTagName
     * @param elementFillerConsume
     * @return instance of xml-writer
     * @author Dharmendrasinh Chudasama
     * @throws ParserConfigurationException
     */
    public static XMLWriter create(String rootElementTagName, Consumer<ElementWrapper> elementFillerConsume) throws ParserConfigurationException {
        return new XMLWriter(rootElementTagName, elementFillerConsume);
    }

    private Document doc;
    public XMLWriter(String rootElementTagName, Consumer<ElementWrapper> elementFillerConsume) throws ParserConfigurationException {
        doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
//      doc.setXmlStandalone(true);

        ElementWrapper wrapper = ElementWrapper.createChildWrapper(doc, doc, rootElementTagName);

        //fill
        elementFillerConsume.accept(wrapper);
    }

    public String toXMLString() throws TransformerException {
/*      StringBuilderWriter writer = new StringBuilderWriter();
        writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append(System.lineSeparator());
        write(writer);
        return writer.toString().replace("/>", " />");*/
        //OR
/*      StringBuilderWriter writer = new StringBuilderWriter();
        write(writer);
        return writer.toString();*/
        //OR
        ByteArrayOutputStream out = new ByteArrayOutputStream(700);
        write(out);
        return out.toString();
    }

    public void write(File out) throws TransformerException {
        write(new StreamResult(out));
    }
    
    public void write(OutputStream out) throws TransformerException {
        write(new StreamResult(out));
    }
    
    public void write(Writer out) throws TransformerException {
        write(new StreamResult(out));
    }

    private void write(Result result) throws TransformerException {
        //export
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.METHOD,"xml");
        transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
        transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");//in multi lines, def="no"
//      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");//remove<?xml ..?> tag, def="no"
//      transformer.setOutputProperty(OutputKeys.STANDALONE,"no");
//      transformer.setOutputProperty(OutputKeys.MEDIA_TYPE,"text/xml");
//      transformer.setOutputProperty("xalan:indent-amount", "0"); //def="0"
//      transformer.setOutputProperty("xalan:content-handler", "org.apache.xml.serializer.ToXMLStream");
//      transformer.setOutputProperty("xalan:entities", "org/apache/xml/serializer/XMLEntities");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");//prefix spaces before tags, def="0"

        transformer.transform(new DOMSource(doc), result);
    }


    /**
     * @author Dharmendrasinh Chudasama
     */
    public static class ElementWrapper {
        private Element element;

        private ElementWrapper(Element element) {
            this.element = element;
        }

        public Element getElement() {
            return element;
        }
        
        public Document getDoc() {
            return getElement().getOwnerDocument();
        }

        private static Element createChildElement(final Document doc, final Node parent, final String childTagName){
            Element child = doc.createElement(childTagName);
            parent.appendChild(child);
            return child;
        }

        private static ElementWrapper createChildWrapper(final Document doc, final Node parent, final String childTagName){
            Element child = createChildElement(doc, parent, childTagName);
            return new ElementWrapper(child);
        }

        /**create and append child tag to current element
         * @return created child tag
         */
        public Element createChildElement(String tagName){
            return createChildElement(getDoc(), getElement(), tagName);
        }

        public ElementWrapper createChildWrapper(final String childTagName){
            return createChildWrapper(getDoc(), getElement(), childTagName);
        }

        public void childText(String textContent){
            if(textContent != null && !textContent.isEmpty()){
                Text textNode = getDoc().createTextNode(textContent);
                getElement().appendChild(textNode);
            }
        }
/*      public ElementWrapper child(String tagName){
            return new ElementWrapper(getDoc(), createChild(tagName));
        }
*/
        /** append tag with string content */
        public void child(String tagName, String textContent){
            createChildWrapper(tagName).childText(textContent);
        }
        
        /**
         * @param parent
         * @param tagName
         * @return child element
         */
/*      public Element child(Element parent, String tagName){
            final Document doc = parent.getOwnerDocument();
            Element element = doc.createElement(tagName);
            parent.appendChild(element);
            return element;
        }*/

        public void child(String tagName, Consumer<ElementWrapper> elementConsumer){
            elementConsumer.accept(createChildWrapper(tagName));
        }

        /** @param dataMap {tagName, contentText}
         * @see #child(String, String)
         */
        public void child(Map<String,String> dataMap){
            dataMap.forEach((tagName,contentText)->child(tagName, contentText));
        }

        public void children(String[] childLoopTree, Consumer<ElementWrapper> lastChildConsumer){
            final Document doc = getDoc();
            Element element = getElement();
            for (String tagName : childLoopTree) {
                element = createChildElement(doc, element, tagName);
            }
            lastChildConsumer.accept(new ElementWrapper(element));
        }
        
        /** Add / replace attribute */
        public void attr(String attrName, String value){
            getElement().setAttribute(attrName, value);
        }

        public void attr(Map<String,String> dataMap){
            dataMap.forEach((attrName,value)->attr(attrName, value));
        }

    }

    

/*
    //example
    public static void main(String[] args) throws Exception {
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        XMLWriter.create("html", html->{
            html.childs(new String[]{"head","title"}, title->title.childText("My TITLE"));
            html.child("body", body->{
                body.attr("bgcolor", "red");

                body.child("div", div->{
                    Map<String, String> userMap = new LinkedHashMap<String, String>();
                    userMap.put("roll-no", "1");
                    userMap.put("name", "Dharm");
                    div.child(userMap);
                });
                body.child("div", div->{
                    Map<String, String> userMap = new LinkedHashMap<String, String>();
                    userMap.put("roll-no", "2");
                    userMap.put("name", "Rajan");
                    div.child(userMap);
                });
            });
        }).write(out);

        System.out.println(out.toString());
    }
*/

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM