Reputation: 295
Here is my Code so far:
// locate the node(s)
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xpath.evaluate("//root[text()='input[1]']", doc, XPathConstants.NODESET);
// make the change
for (int idx = 0; idx < nodes.getLength(); idx++) {
nodes.item(idx).setTextContent(input[3]);
}
// save the result
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(new DOMSource(doc), new StreamResult(new File(outputFile)));
Input[1] is what I am looking for in the XML, and input [3] is what it is being replaced with.
Here is the XML:
<root>
<accounts>
<account name="Bill Gates">
<position>CEO</position>
<phoneNumber>123-485-1854</phoneNumber>
<notes>Runs the company</notes>
</account>
<account name="Service Account"/>
<account name="Burt Mackland">
<position>CFO</position>
<phoneNumber>345-415-4813</phoneNumber>
<notes>Great CFO</notes> </account>
<account name="Joe Smith">
<position>Accountant</position>
<reportsTo>Burt Mackland</reportsTo>
<phoneNumber>135-118-7815</phoneNumber>
<notes>Must have ID checked at all Gates</notes>
</account>
</accounts>
<departments>
<deparment name="Finance">
<employeeCount>2</employeeCount>
</deparment>
<department name="Human Resources">
<employeeCount>0</employeeCount>
</department>
<department name="Executive">
<employeeCount>2</employeeCount>
</department>
</departments>
</root>
The user may not know what is in the XML. So i cannot hardcode the Xpath in the code. Please any would be greatly appreciated!
Upvotes: 6
Views: 12982
Reputation: 135762
As you want to search for text in any element (not only <root>
), change the XPath expression from
//root[text()='TEXT-TO-BE-FOUND']
To
//*[text()='TEXT-TO-BE-FOUND']
To find all attributes with the same value, you must use the following XPath expression:
//*/@*[.='TEXT-TO-BE-FOUND']
Also, as you can't hardcode, make TEXT-TO-BE-FOUND
a variable. (Note: TEXT-TO-BE-FOUND
must be escaped, it may not contain '
as it will affect the XPath expression.)
import java.io.File;
import java.util.Scanner;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import org.w3c.dom.*;
public class XmlChange {
public static void main(String argv[]) throws Exception {
Scanner keyboard = new Scanner(System.in);
System.out.print("Type like textToFind,textToReplace: "); // type, for example CEO,Chief Executive Officer
String next = keyboard.nextLine();
String[] input = next.split(",");
String textToFind = input[0].replace("'", "\\'"); //"CEO";
String textToReplace = input[1].replace("'", "\\'"); // "Chief Executive Officer";
String filepath = "root.xml";
String fileToBeSaved = "root2.xml";
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filepath);
XPath xpath = XPathFactory.newInstance().newXPath();
// change ELEMENTS
String xPathExpression = "//*[text()='" + textToFind + "']";
NodeList nodes = (NodeList) xpath.evaluate(xPathExpression, doc, XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
nodes.item(idx).setTextContent(textToReplace);
}
// change ATTRIBUTES
String xPathExpressionAttr = "//*/@*[.='" + textToFind + "']";
NodeList nodesAttr = (NodeList) xpath.evaluate(xPathExpressionAttr, doc, XPathConstants.NODESET);
for(int i=0; i<nodesAttr.getLength(); i++) {
nodesAttr.item(i).setTextContent(textToReplace);
}
System.out.println("Everything replaced.");
// save xml file back
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(fileToBeSaved));
transformer.transform(source, result);
}
}
Upvotes: 8