如何使用Java编辑文件对象中的XML节点

时间:2009-10-30 01:09:31

标签: java xml

互联网上有很多关于“阅读”文件的例子,但我找不到任何关于“编辑”节点值并将其写回原始文件的内容。

我有一个非工作 xml编写器类,如下所示:

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

    public static Document xmlDocument;

    public static void main(String[] args) 
           throws TransformerException, IOException {
        try {
            xmlDocument = 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();
        } 
    }
}

对于这个例子,假设这是XML,我想添加一个“C”节点(在A节点内),其中包含值“New”

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

2 个答案:

答案 0 :(得分:6)

使用Document对象创建新节点。按照建议添加节点包括创建节点,设置其内容,然后将其附加到根元素。在这种情况下,您的代码看起来像这样:

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

这将在B节点之后将C节点添加为A的新子节点。

此外,Element还有一些便利功能,可以减少所需的代码量。上面的第二行可能已被替换为

e.setTextContent("new");

涉及非根元素的更复杂的工作将涉及您使用XPath来获取要编辑的目标节点。如果您确实开始使用XPath来定位节点,请记住JDK XPath性能非常糟糕。尽可能避免使用"@foo"的XPath支持e.getAttribute("foo")之类的构造。

编辑:将文档格式化为可写入文件的字符串可以使用以下代码完成。

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

编辑:回复:用代码更新问题。

您的代码不起作用,因为您正在混淆“路径”和“元素名称”。 Document.createElement()的参数是新节点的名称,而不是放置它的位置。在我编写的示例代码中,我没有找到适当的节点,因为您特别询问了如何向文档父元素添加节点。如果您希望addElement()的行为符合我认为您期望它的行为,则必须为目标父节点的xpath添加另一个参数。

您的代码的另一个问题是您的writeDoc()函数没有任何输出。我的示例显示将XML写入String值。您可以通过调整代码将其写入您想要的任何编写器,但在您的示例代码中,您使用StringWriter但从不从中提取写入的字符串。

我建议重写你的代码

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();
    }
}

答案 1 :(得分:1)

为了将文档写回文件,您需要一个XML序列化程序或自己编写。如果您使用的是Xerces库,请查看XMLSerializer。对于样本用法,您还可以查看DOMWriter样本页面。

有关Xerces的更多信息,read this