2011-05-25 68 views
17

我有一個XML文檔和該文檔的XPath表達式。我必須在運行時使用XPath來更新文檔。如何使用XPath和Java更新XML

如何使用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下姓名和年齡的值。

回答

23

使用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寫到一個XML文件修改完的DOM後?如果是這樣,這裏是如何做到這一點的兩個例子:

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

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

+0

在這一步我已經done.but現在如何設置這個節點對象到document.we不能使用doc.appendChild(myNodeList.item(0));.因爲我們不想追加我想要的新節點只需設置一個元素的值。爲此,我們是否需要刪除舊節點並添加具有更新值的另一個節點......? – samash 2011-05-26 11:53:29

+0

謝謝。如果我需要更改節點屬性怎麼辦? – Dejell 2014-07-21 10:48:32

3

XPath用於選擇XML文檔的某些部分,它沒有提供更新。但是,因爲它返回DOM對象(元素,如果內存服務,或者可能節點),您可以使用DOM方法來更改文檔。

3

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"); 
+0

我可以從xpath表達式獲得Nodelist,但在那之後如何修改這個...你可以把一段代碼示例....我不是XML專家....... – samash 2011-05-25 12:21:59

1

考慮使用XQuery更新替代的XPath。這允許你寫

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

這比使用Java DOM API更容易。

+0

但我不知道xquey以及如何將此查詢嵌入到Java ..... – samash 2011-05-26 12:08:27

+0

你能提供一個鏈接到SSSCE嗎? – 2013-10-21 13:21:15

+0

@samesh然後你發現了。 – 2013-10-21 14:51:05

1

我創建了一個小項目使用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(); 
2

您可以刪除該文件並創建一個新的。

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

這裏是改變與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"); 
    } 
}