Writing from Java to an XML document - Simple

2019-05-11 16:41发布

问题:

I know there's tons of questions on writing from Java to XML on stackoverflow, but it's all too complex. I feel I have a very simple problem that I just can't figure out.

So I have a program that takes a bunch of user input and I have it currently creating and appending a text document with the results. I'll just post my writer code here:

 PrintWriter out = null;
         try {
             out = new PrintWriter(new BufferedWriter(new FileWriter("C:/Documents and Settings/blank/My Documents/test/test.txt", true)));
             out.println("");
             out.println("<event title=\""+titleFieldUI+"\"");
             out.println("  start=\""+monthLongUI+" "+dayLongUI+" "+yearLongUI+" 00:00:00 EST"+"\"");            
             out.println("  isDuration=\"true\"");
             out.println("  color=\""+sValue+"\"");
             out.println("  end=\""+monthLong1UI+" "+dayLong1UI+" "+yearLong1UI+" 00:00:00 EST"+"\"");
             out.println("  "+descriptionUI);
             out.println("");
             out.println("</event>");
             out.println("  <!-- Above event added by: " +System.getProperty("user.name")+" " +
                        "on: "+month+"/"+day+"/"+year+" -->");       
         }catch (IOException e) {
             System.err.println(e);
         }finally{
             if(out != null){
                 out.close();
             }
         } 

So in the end, I want it to write to an already existing XML file (which I can do by simply changing where my writer goes to). Problem is, this XML file has ONE root tag known as <data>. I need the results of my program to go on the bottom of the XML file, but come BEFORE </data>. That's the only requirement. Everything I find seems too complex and I can't figure it out..

Any help is very much appreciated!

回答1:

You should use a decent XML API. For example, here's an example using JDOM:

import java.io.*;

import org.jdom2.*;
import org.jdom2.input.*;
import org.jdom2.output.*;

public class Test {
    public static void main(String args[]) throws IOException, JDOMException {
        File input = new File("input.xml"); 
        Document document = new SAXBuilder().build(input);
        Element element = new Element("event");
        element.setAttribute("title", "foo");
        // etc...
        document.getRootElement().addContent(element);

        // Java 7 try-with-resources statement; use a try/finally
        // block to close the output stream if you're not using Java 7
        try(OutputStream out = new FileOutputStream("output.xml")) {
            new XMLOutputter().output(document, out);
        }
    }
}

It's really not that hard... and it'll be much, much more robust than writing it out manually. (For example, this will do the right thing if your event title contains "&" - whereas your code would have produced invalid XML.)



回答2:

If you like fluent api, then you can use JOOX:

File file = new File("projects.xml");

Document document = $(file).document();

Comment eventComment = document.createComment("Above event added by: "
        + System.getProperty("user.name") + "\n" +
        " on: " + month + "/" + day + "/" + year);

document = $(file)
        .xpath("//data")
        .append($("event",
                $("title", "titleFieldUI"),
                $("start", monthLongUI + " " + dayLongUI + " " + yearLongUI + " 00:00:00 EST"),
                $("isDuration", "true"),
                $("color", sValue),
                $("end", monthLong1UI + " " + dayLong1UI + " " + yearLong1UI + " 00:00:00 EST")))
        .append($(eventComment))
        .document();

Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(file);
Source input = new DOMSource(document);

transformer.transform(input, output);

or XMLBuilder

XMLBuilder builder = XMLBuilder.parse(
        new InputSource(new FileReader("C:/Documents and Settings/blank/My Documents/test/test.txt")))
        .xpathFind("//data")
        .e("event")
        .a("title", titleFieldUI)
        .a("start", monthLongUI + " " + dayLongUI + " " + yearLongUI + " 00:00:00 EST")
        .a("isDuration", "true")
        .a("color", sValue)
        .a("end", monthLong1UI + " " + dayLong1UI + " " + yearLong1UI + " 00:00:00 EST")
        .up()
        .comment("Above event added by: " + System.getProperty("user.name") + "\n" +
                " on: " + month + "/" + day + "/" + year);

PrintWriter writer = new PrintWriter(new FileOutputStream("C:/Documents and Settings/blank/My Documents/test/test.txt"));
builder.toWriter(writer, new Properties());


回答3:

You could use JOOX. This is how you would do an append:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document doc = parser.parse("/pathToXML");

JOOX.$(doc).append("<newNode>data<newNode>");

By default the $(doc) will load the root node. If you want an inner node you can use the find() method. The library is not documented very well but being open source you can always directly check the sources.