开发者

How do I edit a XML node in a file object, using Java

There are a lot of examples on the internet of "reading" files but I can't find anything on "editing" a node value and writing it back out to the original file.

I have a non-working xml writer class that looks like this:

import org.w3c.dom.Document;
public class RunIt {

    public static Document xmlDocument;

    public static void main(String[] args) 
           throws TransformerException, IOException {
        try {
            xmlDocumen开发者_如何学Ct = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder().parse("thor.xml");            
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (SAXException ex) {
            ex.printStackTrace();
        } catch (ParserConfigurationException ex) {
            ex.printStackTrace();
        } 
        addElement("A", "New");
        writeDoc();
    }

    public static void addElement(String path, String val){
        Element e = xmlDocument.createElement(path);
        e.appendChild(xmlDocument.createTextNode(val));
        xmlDocument.getDocumentElement().appendChild(e);
    }

    public static void writeDoc() throws TransformerException, IOException {
        StringWriter writer = new StringWriter(); 
        Transformer tf;
        try {
            tf = TransformerFactory.newInstance().newTransformer();
            tf.transform(new DOMSource(xmlDocument), new StreamResult(writer)); 
            writer.close();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerFactoryConfigurationError e) {
            e.printStackTrace();
        } 
    }
}

For this example, lets say this is the XML and I want to add a "C" node (inside the A node) that contains the value "New" :

 <A>
   <B>Original</B>
 </A>


You use the Document object to create new nodes. Adding nodes as you suggest involves creating a node, setting its content and then appending it to the root element. In this case your code would look somehting like this:

Element e = xmlDocument.createElement("C");
e.appendChild(xmlDocument.createTextNode("new"));
xmlDocument.getDocumentElement().appendChild(e);

This will add the C node as a new child of A right after the B node.

Additionally, Element has some convenience functions that reduce the amount of required code. The second line above could have been replaced with

e.setTextContent("new");

More complicated efforts involving non root elements will involve you using XPath to fetch the target node to be edited. If you do start to use XPath to target nodes, bear in mind that the JDK XPath performance is abysmal. Avoid using an XPath of "@foo" in favor of constructs like e.getAttribute("foo") whenever you can.

EDIT: Formatting the document back to a string which can be written to a file can be done with the following code.

 Document xmlDocument;
 StringWriter writer = new StringWriter();
 TransformerFactory.newInstance().transform(new DOMSource(xmlDocument), new StreamResult(writer));
 writer.close();
 String xmlString = writer.toString();

EDIT: Re: updated question with code.

Your code doesn't work because you're conflating 'path' and 'element name'. The parameter to Document.createElement() is the name of the new node, not the location in which to place it. In the example code I wrote I didn't get into locating the appropriate node because you were asking specifically about adding a node to the document parent element. If you want your addElement() to behave the way I think you're expecting it to behave, you'd have to add another parameter for the xpath of the target parent node.

The other problem with your code is that your writeDoc() function doesn't have any output. My example shows writing the XML to a String value. You can write it to any writer you want by adapting the code, but in your example code you use a StringWriter but never extract the written string out of it.

I would suggest rewriting your code something like this

public static void main(String[] args) {
    File xmlFile = new File("thor.xml");
    Document xmlDocument = DocumentBuilderFactory.newInstance()
          .newDocumentBuilder().parse(xmlFile);
    // this is effective because we know we're adding to the 
    // document root element
    // if you want to write to an arbitrary node, you must 
    // include code to find that node
    addTextElement(xmlDocument.getDocumentElement(), "C", "New");
    writeDoc(new FileWriter(xmlFile);
}

public static Element addTextElement(Node parent, String element, String val){
    Element e = addElement(parent, element)
    e.appendChild(xmlDocument.createTextNode(val));
    return e;
}

public static Element addElement(Node parent, String element){
    Element e = xmlDocument.createElement(path);
    parent.appendChild(e);
    return e;
}

public static void writeDoc(Writer writer) {
    try {
      Transformer tf = TransformerFactory.newInstance().newTransformer();
      tf.transform(new DOMSource(xmlDocument), new StreamResult(writer)); 
    } finally {
      writer.close();
    }
}


In order to write your document back to a file, you'll need an XML serializer or write your own. If you are using the Xerces library, check out XMLSerializer. For sample usage, you can also check out the DOMWriter samples page.

For more information on Xerces, read this

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜