【问题标题】:How to update XML using XPath and Java如何使用 XPath 和 Java 更新 XML
【发布时间】:2011-09-01 17:27:07
【问题描述】:

我有一个 XML 文档和该文档的 XPath 表达式。我必须在运行时使用 XPath 更新文档。

如何使用 Java 做到这一点?

下面是我的xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<PersonList>
    <Person>
        <Name>Sonu Kapoor</Name>
        <Age>24</Age>
        <Gender>M</Gender>
        <PostalCode>54879</PostalCode>
    </Person>
    <Person>
        <Name>Jasmin</Name>
        <Age>28</Age>
        <Gender>F</Gender>
        <PostalCode>78745</PostalCode>
    </Person>
    <Person>
        <Name>Josef</Name>
        <Age>232</Age>
        <Gender>F</Gender>
        <PostalCode>53454</PostalCode>
    </Person>
</PersonList>

我必须更改//PersonList/Person[2]/Name 下的姓名和年龄的值。

【问题讨论】:

    标签: java xml xpath


    【解决方案1】:

    这是一个超酷的功能,您可以使用其xpath 修改任何 XML 文档的任何标记值。您需要传递三个参数 xmlxpathExpressionnewValue,它会将 XML 文件返回为 String 并修改值。

    如果要将 XML 作为文件传递,则需要相应地更改函数。但是逻辑是一样的。

     public String updateXML(String xml, String xpathExpression, String newValue)
     {
        try {
            //Creating document builder
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            Document document = builder.parse(new org.xml.sax.InputSource(new StringReader(xml)));
          
            //Evaluating xpath expression using Element
            XPath xpath = XPathFactory.newInstance().newXPath();
            Element element = (Element)xpath.evaluate(xpathExpression, document, XPathConstants.NODE);
            
            //Setting value in the text
            element.setTextContent(value);
    
            //Transformation of document to xml
            StringWriter stringWriter = new StringWriter();
            Transformer xformer = TransformerFactory.newInstance().newTransformer();
            xformer.transform(new DOMSource(document), new StreamResult(stringWriter));
    
            xml = stringWriter.toString();
            } 
            catch (Exception e) 
            {
               e.printStackTrace();
            }
        return xml;
    }
    

    【讨论】:

    • xpath.evaluate(xpathExpression, document, XPathConstants.NODE); 返回 org.w3c.dom.Node 但没有 Element
    【解决方案2】:

    这是用vtd-xml 更改内容的代码...vtd-xml 的独特之处在于它是唯一提供增量更新功能的API。

    import com.ximpleware.*;
    import java.io.*;
    
    public class changeName {
        public  static  void main(String s[]) throws VTDException,java.io.UnsupportedEncodingException,java.io.IOException{
            VTDGen vg = new VTDGen();
            if (!vg.parseFile("input.xml", false))
                return;
            VTDNav vn = vg.getNav();
            AutoPilot ap = new AutoPilot(vn);
            XMLModifier xm = new XMLModifier(vn);
            ap.selectXPath("//PersonList/Person[2]");
            int i=0;
            while((i=ap.evalXPath())!=-1){
                if (vn.toElement(VTDNav.FIRST_CHILD,"Name")){
                     int k=vn.getText();
                     if (i!=-1)
                        xm.updateToken(k, "Jonathan"); 
                     vn.toElement(VTDNav.PARENT);
                }
                if (vn.toElement(VTDNav.FIRST_CHILD,"Age")){
                     int k=vn.getText();
                     if (i!=-1)
                        xm.updateToken(k, "42"); 
                     vn.toElement(VTDNav.PARENT);
                }
            }
            xm.output("new.xml");
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以删除该文件并创建一个新文件。

      Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
          new InputSource("data.xml"));
      
      XPath xpath = XPathFactory.newInstance().newXPath();
      NodeList nodes = (NodeList) xpath.evaluate("//employee/name[text()='old']", doc,
          XPathConstants.NODESET);
      
      for (int idx = 0; idx < nodes.getLength(); idx++) {
        nodes.item(idx).setTextContent("new value");
      }
      
      Transformer xformer = TransformerFactory.newInstance().newTransformer();
      xformer.transform(new DOMSource(doc), new StreamResult(new File("data_new.xml")));
      

      【讨论】:

        【解决方案4】:

        我创建了一个使用 XPATH 创建/更新 XML 的小项目: https://github.com/shenghai/xmodifier 更改 xml 的代码如下:

        Document document = readDocument("personList.xml");
        XModifier modifier = new XModifier(document);
        modifier.addModify("//PersonList/Person[2]/Name", "newName");
        modifier.modify();
        

        【讨论】:

          【解决方案5】:

          使用setNodeValue。首先,获取一个NodeList,例如:

          myNodeList = (NodeList) xpath.compile("//MyXPath/text()")
                     .evaluate(myXmlDoc, XPathConstants.NODESET);
          

          然后设置例如的值第一个节点:

          myNodeList.item(0).setNodeValue("Hi mom!");
          

          更多示例,例如here.

          正如这里的其他两个答案以及您的previous question 中提到的:从技术上讲,XPath 不是一种“更新”XML 文档的方法,而只是定位 XML 文档中的节点。但我认为以上是你想要的。

          编辑:回复您的评论...您是在询问如何在完成 DOM 编辑后将您的 DOM写入到 XML 文件中?如果是这样,这里有两个例子说明如何做到这一点:

          http://www.java2s.com/Code/Java/XML/WriteDOMout.htm

          http://download.oracle.com/javaee/1.4/tutorial/doc/JAXPXSLT4.html

          【讨论】:

          • 在这一步我已经完成了。但是现在如何将此节点对象设置为文档。我们不能使用 doc.appendChild(myNodeList.item(0));.因为我们不想要追加新节点我只想设置一个元素的值。为此,我们是否需要删除旧节点并添加另一个具有更新值的节点...????
          • 谢谢。如果我需要更改节点属性怎么办?
          • 如果您选择一个节点并省略索引访问myNodeList.item(0),则可以只使用XPathConstants.NODE,因为评估将返回Node
          【解决方案6】:

          考虑使用 XQuery 更新而不是 XPath。这允许您编写

          replace value of node //PersonList/Person[2]/Name with "Anonymous"
          

          这比使用 Java DOM API 容易得多。

          【讨论】:

          • 使用 XQuery 的缺点:AFAIK 在“标准”JDK(最高 v8)中没有默认的 XQuery 实现 -> 需要额外的库/依赖项
          • 下载 JAR 文件并将其添加到类路径中对于任何 Java 程序员来说无疑是必不可少的!
          【解决方案7】:

          XPath 可用于选择文档中的节点,不能用于修改

          您将 xpath 表达式应用于您的文档并获得一个元素(在您的情况下)。一旦你有了这个Element,你就可以使用Element 方法来改变值(你的名字和年龄)


          NodeList 开始,它应该像这样工作:

          NodeList nodes = getNodeListFromXPathExpression();  // you know how
          if (nodes.length == 0)
             return;  // empty nodelist, xpath didn't select anything
          
          Node first = node.getItem(0);    // take the first from the list, your element
          
          // this is a shortcut for your example:
          //  first is the actual selected element (a node)
          //  .getFirst() returns the first child node, the "text node" (="Jasmine", ="28")
          //  .setNodeValue() replace the actual value of that text node with a new string
          first.getFirstChild().setNodeValue("New Name or new age");
          

          【讨论】:

          • 我可以从 xpath 表达式中获取 Nodelist,但之后如何修改...你能放一段示例代码吗....我不是 XML 专家..... ..
          【解决方案8】:

          XPath 用于选择 XML 文档的一部分。它不提供更新。但是由于它返回 DOM 对象(元素,如果内存服务,或者可能是节点),您可以使用 DOM 方法来更改文档。

          【讨论】:

            猜你喜欢
            • 2015-11-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-20
            • 1970-01-01
            • 2011-05-29
            相关资源
            最近更新 更多