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

时间:2021-04-02 07:15:34

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.

internet上有很多“读取”文件的示例,但是我在“编辑”节点值并将其写回原始文件时找不到任何内容。

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

我有一个不工作的xml writer类,看起来是这样的:

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

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" :

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

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

2 个解决方案

#1


6  

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:

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

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.

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

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.

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

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.

您的代码不能工作,因为您合并了“path”和“element name”。Document.createElement()的参数是新节点的名称,而不是放置它的位置。在我编写的示例代码中,我没有找到合适的节点,因为您特别要求向文档父元素添加节点。如果希望addElement()按照我认为的那样运行,则必须为目标父节点的xpath添加另一个参数。

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.

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

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

#2


1  

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.

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

For more information on Xerces, read this

有关Xerces的更多信息,请阅读本文

#1


6  

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:

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

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.

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

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.

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

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.

您的代码不能工作,因为您合并了“path”和“element name”。Document.createElement()的参数是新节点的名称,而不是放置它的位置。在我编写的示例代码中,我没有找到合适的节点,因为您特别要求向文档父元素添加节点。如果希望addElement()按照我认为的那样运行,则必须为目标父节点的xpath添加另一个参数。

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.

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

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

#2


1  

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.

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

For more information on Xerces, read this

有关Xerces的更多信息,请阅读本文

相关文章