1

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.

1
  • i am only looking for the part of applying the xpath, getting the result and then replacing it specifically, everything else is just detail Commented Jun 16, 2012 at 19:12

3 Answers 3

2

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

}
Sign up to request clarification or add additional context in comments.

1 Comment

What if the parent has 5 child and you are going to remove forth child, so you can't use append it will add as the latest child. have any idea for this ?
1
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)));

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.