使用Java中的String替换XML文档中的元素

时间:2012-06-16 19:04:38

标签: java xml xpath

我正在编写HTTP服务器,我将在HTTP PUT中接收XPATH,并在请求正文中接收数据。

我需要将XPATH表达式的结果替换为XML文档中HTTP请求数据中的数据

例如

XML文档是

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

HTTP请求例如是

  PUT /pidf-manipulation/users/sip:someone@example.com/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>

上面的内容应该用PUT请求替换XML中的note元素。客户端可以通过这种方式发送任何XPATH并替换XML文档的内容。

请帮助您了解如何在Java代码中完成此操作。

3 个答案:

答案 0 :(得分:1)

基本上你需要做的是:

  1. 加载要更改的xml;
  2. 在替换中加载要使用的片段;
  3. 在[1]中加载的文档中采用[2]中加载的节点;
  4. 使用XPath查找要替换的节点;
  5. 从[4]中找到的父节点中获取父节点,从父节点中删除[4]中找到的节点,然后添加您采用的节点。
  6. 你可以使用类似的东西:

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

答案 1 :(得分:0)

您还可以使用以下命令,而不是删除旧节点并添加新节点: parentNode.replaceChild(injectedNode, nodeFound)。 使用此功能,您可以保持节点顺利

答案 2 :(得分:0)

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