user1461001
user1461001

Reputation: 703

Replacing Elements in a XML document with String in Java

I am writing an HTTP server where i will receive an XPATH in an HTTP PUT and the data in the request body.

I will need to replace the result of the XPATH expression with the data in the HTTP request data in an XML document

For example

the XML document is

<presence>
<tuple id="x8eg92n">
<note> i am reading email 3 times a day </note>
</tuple>
</presence>

The HTTP request is for example something like

  PUT /pidf-manipulation/users/sip:[email protected]/index/
  ~~/presence/tuple%5b@id='x8eg92n'%5d/note HTTP/1.1
  If-Match: "xyz"
  Host: xcap.example.com
  Content-Type: application/xcap-el+xml
  ...

  <note>I'm reading mails on Tuesdays and Fridays</note>

This above should replace the note element in the XML with the one the PUT request. Clients can this way send any XPATH and replace contents of the XML document.

Please help in how this can be done in Java Code.

Upvotes: 1

Views: 10114

Answers (3)

ranadheer reddy
ranadheer reddy

Reputation: 21

Node importedTemplateChildNode = targetDoc.importNode(templateChildNode, true);   
// Importing template node to the target document(this solves wrong_DOCUMENT_ERR:)

targetParentNode.replaceChild(importedTemplateChildNode, targetChildnode);       
// Replace target child node with the template node

Transformer tranFac =TransformerFactory.newInstance().newTransformer();
tranFac.transform(new DOMSource(targetDoc), new StreamResult(new FileWriter(targetXmlFile)));

Upvotes: 1

ersefuril
ersefuril

Reputation: 919

Instead of removing old node and adding new node, you could also use : parentNode.replaceChild(injectedNode, nodeFound). With this function, you'll keep your nodes in a good order

Upvotes: 0

Francisco Spaeth
Francisco Spaeth

Reputation: 23903

Basically what you need to do is:

  1. Load the xml to be changed;
  2. Load the fragment you want to use in the replacement;
  3. Adopt node you loaded in [2] in the document you loaded on [1];
  4. Find the node to replace using XPath;
  5. Get the parent node from the one you found in [4], remove the node found in [4] from the parent, and add the node you adopt.

You could use something similar with:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class XmlXPathReplace {

    public static void main(final String[] args) throws SAXException, IOException, ParserConfigurationException,
            XPathExpressionException, TransformerException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true); // never forget this!
        DocumentBuilder builder = factory.newDocumentBuilder();

        // step 1.
        Document doc = builder.parse(new ByteArrayInputStream(( //
                "<?xml version=\"1.0\"?>" + //
                        "<people>" + //
                        "<person><name>First Person Name</name></person>" + //
                        "<person><name>Second Person Name</name></person>" + //
                        "</people>" //
                ).getBytes()));

        // step 2
        String fragment = "<name>Changed Name</name>";
        Document fragmentDoc = builder.parse(new ByteArrayInputStream(fragment.getBytes()));

        // step 3
        Node injectedNode = doc.adoptNode(fragmentDoc.getFirstChild());

        // step 4
        XPath xPath = XPathFactory.newInstance().newXPath();
        XPathExpression expr = xPath.compile("//people/person[2]/name");
        System.out.println();
        Element nodeFound = (Element) expr.evaluate(doc, XPathConstants.NODE);

        // step 5
        Node parentNode = nodeFound.getParentNode();
        parentNode.removeChild(nodeFound);
        parentNode.appendChild(injectedNode);

        DOMSource domSource = new DOMSource(doc);
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        StreamResult result = new StreamResult(new StringWriter());
        transformer.transform(domSource, result);
        System.out.println(result.getWriter().toString());
    }

}

Upvotes: 2

Related Questions