Ändern Sie die XML-Datei mit xPath

Ich möchte eine vorhandene XML-Datei mit xPath ändern. Wenn der Knoten nicht vorhanden ist, sollte er erstellt werden (ggf. zusammen mit den übergeordneten Knoten). Ein Beispiel:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <param0>true</param0>
  <param1>1.0</param1>
</configuration>

Und hier sind ein paar xPaths, die ich einfügen / ändern möchte:

/configuration/param1/text()         -> 4.0
/configuration/param2/text()         -> "asdf"
/configuration/test/param3/text()    -> true

Die XML-Datei sollte danach so aussehen:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <param0>true</param0>
  <param1>4.0</param1>
  <param2>asdf</param2>
  <test>
    <param3>true</param3>
  </test>
</configuration>

Ich habe es versucht:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

try {
  DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
  Document doc = domFactory.newDocumentBuilder().parse(file.getAbsolutePath());
  XPath xpath = XPathFactory.newInstance().newXPath();

  String xPathStr = "/configuration/param1/text()";
  Node node = ((NodeList) xpath.compile(xPathStr).evaluate(doc, XPathConstants.NODESET)).item(0);
  System.out.printf("node value: %s\n", node.getNodeValue());
  node.setNodeValue("4.0");

  TransformerFactory transformerFactory = TransformerFactory.newInstance();
  Transformer transformer = transformerFactory.newTransformer();
  transformer.transform(new DOMSource(doc), new StreamResult(file));
} catch (Exception e) {
  e.printStackTrace();
}

Der Knoten wird in der Datei geändert, nachdem dieser Code ausgeführt wurde. Genau das, was ich wollte. Aber wenn ich einen der folgenden Pfade benutze,node ist null (und daher aNullPointerException ist geworfen):

/configuration/param2/text()
/configuration/test/param3/text()

Wie kann ich diesen Code ändern, damit der Knoten (und auch nicht vorhandene übergeordnete Knoten) erstellt werden?

BEARBEITEN: Ok, zur Verdeutlichung: Ich habe eine Reihe von Parametern, die ich in XML speichern möchte. Während der Entwicklung kann sich dieser Satz ändern (einige Parameter werden hinzugefügt, einige werden verschoben, einige werden entfernt). Ich möchte also im Grunde eine Funktion haben, um den aktuellen Parametersatz in eine bereits vorhandene Datei zu schreiben. Es sollte die bereits in der Datei vorhandenen Parameter überschreiben, neue Parameter hinzufügen und alte Parameter dort belassen.

Das selbe für das Lesen, ich könnte den xPath oder einige andere Koordinaten gerade haben und den Wert vom XML erhalten. Ist dies nicht der Fall, wird die leere Zeichenfolge zurückgegeben.

Ich habe keine Einschränkungen hinsichtlich der Implementierung, xPath, DOM, SAX, XSLT ... Die Verwendung sollte einfach sein, sobald die Funktionalität einmal geschrieben ist (wie bei BeniBelas Lösung).

Also wenn ich folgende Parameter einstellen muss:

/configuration/param1/text()         -> 4.0
/configuration/param2/text()         -> "asdf"
/configuration/test/param3/text()    -> true

Das Ergebnis sollte das Start-XML + diese Parameter sein. Wenn sie an diesem xPath bereits vorhanden sind, werden sie ersetzt, andernfalls werden sie an diesem Punkt eingefügt.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage