问题
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
回答1:
If you just want to write an XML document having exact control over the creating of elements, attributes and other document components, you may use the XMLStreamWriter from the StAX API.
回答2:
My 2 cents goes to java-xmlbuilder. Only for building though. It's hell a lot less complicated than JAXP.
回答3:
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
回答4:
Hope following code will help you
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());
}
*/
}
来源:https://stackoverflow.com/questions/22023460/what-is-the-best-way-to-create-xml-files-in-java