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

dja*_*fan 1 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();
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

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

 <A>
   <B>Original</B>
 </A>
Run Code Online (Sandbox Code Playgroud)

Jhe*_*ico 6

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

Element e = xmlDocument.createElement("C");
e.appendChild(xmlDocument.createTextNode("new"));
xmlDocument.getDocumentElement().appendChild(e);
Run Code Online (Sandbox Code Playgroud)

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

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

e.setTextContent("new");
Run Code Online (Sandbox Code Playgroud)

涉及非根元素的更复杂的工作将涉及您使用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();
Run Code Online (Sandbox Code Playgroud)

编辑:回复:更新问题与代码.

您的代码不起作用,因为您正在混淆"路径"和"元素名称".参数to 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();
    }
}
Run Code Online (Sandbox Code Playgroud)