I am using DOM parser and XPATH to parse a my XML file. I have changed a value of a node in the Document Object. However when I open my XML file, it doesn't show me any reflection. My DOM parser code is as below :
private void setPortNumber(int portNumber) {
try {
Document parsedDocument = parseDocument(tempPath + "/apache-6/conf/server.xml");
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr;
expr = (XPathExpression) xPath.compile("//Connector");
Object result = expr.evaluate(parsedDocument, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
Node node =nodes.item(i);
NamedNodeMap attributes = node.getAttributes();
for(int j=0; j< attributes.getLength(); j++){
String value = attributes.item(j).getNodeValue();
if(value.equals("HTTP/1.1")){
Node valueNode = attributes.item(0);
valueNode.setNodeValue(portNumber+"");
}
}
}
} catch (XPathExpressionException e) {}
}
private Document parseDocument(String xmPath) {
Document doc = null;
try {
DocumentBuilderFactory domFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
builder = domFactory.newDocumentBuilder();
doc = builder.parse(xmPath);
}catch (Exception e) {}
return doc;
}
How can I save my document after done with changes?
Can anyone help me to resolve this?
Here is the sample code for updating an XML file
try
{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filePath);
Node rootNode = doc.getFirstChild();//for getting the root node
String expersion="books/author";//x-path experssion
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile(expersion);
Node updateNode=null;
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
updateNode=nodes.item(0);
updateNode.appendChild(doc.createCDATASection("new value"));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult streamResult = new StreamResult(new File(filePath));
transformer.transform(source, streamResult);
}
catch (Exception e) {
e.printStackTrace();
}
You could use the Transformer API to write your DOM to a stream or a file.
You have to transform the dom object into an XML using the transformer.
http://download.oracle.com/javaee/1.4/tutorial/doc/JAXPXSLT4.html
Related
I want to check if an Element exists by using the attribute uuid.
Here's an example how the file looks like:
<?xml version="1.0" encoding="utf-8"?>
<Test1>
<typ>task</typ>
<datestamp>20150602153306</datestamp>
<datecreate>20150602153306</datecreate>
<task uuid="92F7F685-C370-4E55-9026-020E3CDCEDE0" status="0">
<task_headline>TEST2000</task_headline>
<task_subject>There is a Problem.</task_subject>
<task_action>Solve it!</task_action>
<task_priority color="#E62C29">high</task_priority>
<task_note></task_note>
</task>
<task uuid="92F7F685-C370-4E55-4464-ADWI290ASD" status="0">
<task_headline>TEST3000</task_headline>
<task_subject>Another Problem</task_subject>
<task_action>Solve it again.</task_action>
<task_priority color="#E62C29">high</task_priority>
<task_image></task_image>
</task>
</Test1>
The Elements that will be tested are <task_note></task_note> and <task_image></task_image>
As you can see, the first task has the <task_note> and is missing the <task_image> element. How can I check if <task_image> exists, and when not create the element.
I know how to create an Element:
note.appendChild(doc.createTextNode(taskItems.get(position).get(task_note)));
EDIT:
Thats the Code I use
File fileDir = new File(getFilesDir(), "job_active");
fileDir.mkdirs();
int position = data.getIntExtra("position", 0);
HashMap<String, String> intentmap = (HashMap<String, String>) data.getSerializableExtra("
taskItems.set(position, intentmap);
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new FileInputStream(new File(fileDir, filenameWithExt)));
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
XPathExpression xPathExpression = xPath.compile("//task[#uuid='" + taskItems.get(position).get(task_uuid) + "']/task_
NodeList nodeList = (NodeList) xPathExpression.evaluate(doc, XPathConstants.NODE);
NodeList taskList = doc.getElementsByTagName("task");
int taskListLength = taskList.getLength();
String uuid = taskItems.get(position).get(task_uuid);
for (int i = 0; i < taskListLength; i++) {
Node node = taskList.item(i);
Node key = node.getAttributes().getNamedItem("uuid");
if (key != null && uuid.equals(key.getNodeValue())) {
Node valueNode = node.getAttributes().getNamedItem("task_status");
valueNode.setTextContent("1000");
}
//Wenn die knoten task_note und task_image existieren sollen sie verändert werden
if (task_note.equals(node.getNodeName())) {
node.setTextContent(taskItems.get(position).get(task_note));
}
if (task_image.equals(node.getNodeName())) {
node.setTextContent(taskItems.get(position).get(task_image));
}
}
if(nodeList==null){
Node tasknote = doc.createElement(task_note);
tasknote.appendChild(doc.createTextNode(taskItems.get(position).get(task_note)));
}
NodeList tasknote = doc.getElementsByTagName(task_note);
if (tasknote == null) {
Element note = doc.createElement(task_note);
if (taskItems.get(position).containsKey(task_note))
if (taskItems.get(position).get(task_note) != null)
note.appendChild(doc.createTextNode(taskItems.get(position).get(task_note)));
// task.appendChild(note);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new FileOutputStream(new File(fileDir, filenameWithExt)));
transformer.transform(source, result);
But I don't know how to check if element exists using the uuid attribute.
I hope you can help me!
Kind Regards!
Following is the code used and below element contents are changed which is not desired by replacing the escape character,
<SelectionFilter>event.ProductType == "CM_Media_Server" and event.ProductVer == "3.0.0.6" and event.ProductPatch == "0"</SelectionFilter>
<SelectionFilter>event.ProductType == "CM_Media_Server" and event.ProductVer == "3.0.0.6" and event.ProductPatch == "0"</SelectionFilter>
Below is the code used,
Document xmlDocument = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(SourceXMLFile);
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression exprPre = xPath
.compile("/SPIRITConfiguration/#Version");
NodeList list = (NodeList) exprPre.evaluate(xmlDocument,
XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
list.item(i).setTextContent(ModelVersion.getValue());
}
// write the content back into new renamed xml file
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(xmlDocument);
StreamResult result = new StreamResult(new File(DestxmlFile));
transformer.transform(source, result);
Kindly help me on this. Thank you in advance.
On your DocumentBuilderFactory, you can call the setExpandEntityReferences method to turn the setting off:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setExpandEntityReferences(false);
Document xmlDocument = factory.newDocumentBuilder().parse(SourceXMLFile);
Suppose I am having following XML File content
<CREDENTIALS>
<SCENERIOONE>
<USERNAME>stackoverflow</USERNAME>
<PASSWORD>argmishra</PASSWORD>
</SCENERIOONE>
<SCENERIOTWO>
<USERNAME>stackexchnage</USERNAME>
<PASSWORD>mishraarg</PASSWORD>
</SCENERIOTWO>
</CREDENTIALS>
I want to retrieve the data for SCENERIOONE(Username and password) and check it and update it if required and similarly for SCENERIOTWO.
I am able to retrieve data if i replaced SCENERIOTWO with SCENERIOONE i.e. child node of CREDENTIALS are same.
But not able to retrieve if child node of one parent node is different.
EDIT:
Now I am able to retrieve the Data from XML by passing Scenario's:-
try {
File file = new File("D://DemoWorkSpace//XMLDemo//lib//MyXMLFile.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
doc.getDocumentElement().normalize();
System.out.println("Root element " + doc.getDocumentElement().getNodeName());
NodeList nodeLst = doc.getElementsByTagName("MEMBER_BENEFITS");
System.out.println("Information of all employees");
for (int s = 0; s < nodeLst.getLength(); s++) {
Node fstNode = nodeLst.item(s);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElmnt = (Element) fstNode;
NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("USERNAME");
Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
NodeList fstNm = fstNmElmnt.getChildNodes();
System.out.println("User Name : " + ((Node) fstNm.item(0)).getNodeValue());
NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("PASSWORD");
Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
NodeList lstNm = lstNmElmnt.getChildNodes();
System.out.println("Password : " + ((Node) lstNm.item(0)).getNodeValue());
}
}
} catch (Exception e) {
e.printStackTrace();
}
But I do not know how to update the XML file?
If I understand correctly, what you're really after is the username/password nodes, regardless of where they are in the document....
You can use XPath to query the document to return what you want, for example...
try (InputStream is = TestXML.class.getResourceAsStream("/Credentials.xml")){
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse(is);
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression xExpress = xpath.compile("//*[USERNAME and PASSWORD]/*");
NodeList nodeList = (NodeList) xExpress.evaluate(dom, XPathConstants.NODESET);
for (int index = 0; index < nodeList.getLength(); index++) {
Node node = nodeList.item(index);
System.out.println(node.getNodeName());
}
} catch (Exception exp) {
exp.printStackTrace();
}
Will output...
USERNAME
PASSWORD
USERNAME
PASSWORD
If it's important, you can use the Nodes parent property to find the parent node and obviously, getTextContent to get the nodes text content
You can manipulate the nodes like normal, based on your needs
Updated
So, based on comments, you should be able to do something like...
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse(new File("Credentials.xml"));
XPath xpath = XPathFactory.newInstance().newXPath();
String scenerio = "SCENERIOONE";
XPathExpression xExpress = xpath.compile("/CREDENTIALS/" + scenerio + "/[USERNAME and PASSWORD]/*");
NodeList nodeList = (NodeList) xExpress.evaluate(dom, XPathConstants.NODESET);
for (int index = 0; index < nodeList.getLength(); index++) {
Node node = nodeList.item(index);
System.out.println(node.getNodeName());
}
} catch (Exception exp) {
exp.printStackTrace();
}
Which will return the USERNAME and PASSWORD nodes for SCENERIOONE
You can use node.get/setTextContent to get/set the text as per normal.
And when you need to, you can use something like...
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.setOutputProperty(OutputKeys.METHOD, "xml");
tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
StreamResult result = new StreamResult(new File("Credentials.xml"));
tf.transform(dom, result);
To save it...
$server_output = "<CREDENTIALS>
<SCENERIOONE>
<USERNAME>stackoverflow</USERNAME>
<PASSWORD>argmishra</PASSWORD>
</SCENERIOONE>
<SCENERIOTWO>
<USERNAME>stackexchnage</USERNAME>
<PASSWORD>mishraarg</PASSWORD>
</SCENERIOTWO>
</CREDENTIALS>";
$xml = simplexml_load_string($server_output);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
foreach ($array as $key => $value) {
$username = $value['USERNAME'];
$password = $value['PASSWORD'];
}
Here is the output:
stackoverflow
argmishra
stackexchnage
mishraarg
How to write xml for Multiple records ?
Desired output
<Root>
<Header>
<HeaderTag>Table of Contents</HeaderTag>
<HeaderRow>
<Content>1.Intoduction</Content>
</HeaderRow>
<HeaderRow>
<Content>2.Basics</Content>
</HeaderRow>
</Header>
</Root>
Need looping or iterator for Header Row to accomodate rows for content as mentioned above.
Appreciate your help.
Using below piece of code
public void createRuleXML() {
try {
String newXmlPath = "C:\\write\\CreatedRuleXml.xml";
DocumentBuilderFactory documentFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentFactory.newDocumentBuilder();
// define root elements
Document document = documentBuilder.newDocument();
Element rootElement = document.createElement("Root");
document.appendChild(rootElement);
// define school elements
Element TocHeader = document.createElement("Header");
rootElement.appendChild(TocHeader);
Element HeaderTag = document.createElement("HeaderTag");
HeaderTag.appendChild(document.createTextNode("Table Of Contents"));
TocHeader.appendChild(HeaderTag);
Element TocHeaderRow = document.createElement("HeaderRow");
TocHeader.appendChild(TocHeaderRow);
Element Content = document.createElement("Content");
Content.appendChild(document.createTextNode("1.Introduction"));
TocHeaderRow.appendChild(Content);
Content.appendChild(document.createTextNode("2.Basics"));
TocHeaderRow.appendChild(Content);
However its is returning
Table Of Contents1.Introduction2.Basics
Got fix with below piece of code.
public void createRuleXML() {
try {
String newXmlPath = "C:\\docwrite\\CreatedRuleXml.xml";
DocumentBuilderFactory documentFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder documentBuilder = documentFactory
.newDocumentBuilder();
// define root elements
Document document = documentBuilder.newDocument();
Element rootElement = document.createElement("Root");
document.appendChild(rootElement);
// define school elements
Element TocHeader = document.createElement("Header");
rootElement.appendChild(TocHeader);
Element HeaderTag = document.createElement("HeaderTag");
HeaderTag.appendChild(document.createTextNode("Table Of Contents"));
TocHeader.appendChild(HeaderTag);
TocHeader.appendChild(getToc(document, "1.Introduction"));
TocHeader.appendChild(getToc(document, "2.Basics"));
// creating and writing to xml file
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource domSource = new DOMSource(document);
StreamResult streamResult = new StreamResult(new File(newXmlPath));
transformer.transform(domSource, streamResult);
System.out.println("File saved to specified path!");
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
}
}
private static Node getToc(Document doc, String tocContent) {
Element tocHeaderRow = doc.createElement("HeaderRow");
//create name element
tocHeaderRow.appendChild(getDetailElements(doc, tocHeaderRow, "Content", tocContent));
return tocHeaderRow;
}
//utility method to create text node
private static Node getDetailElements(Document doc, Element element, String name, String value) {
Element node = doc.createElement(name);
node.appendChild(doc.createTextNode(value));
return node;
}
I am looking for something like this :
<Node1>
<Child2 attr1="abc">
<Child3 attr2="xyz">
<Node1>
From Node1 , I want to get the contents inside the node as text. The output I want is
"<Child2 attr1="abc"><Child3 attr2="xyz">"
//Parse the input document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("yourfile.xml"));
//Set up the transformer to write the output string
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty("indent", "yes");
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
//Find the first child node
NodeList nl = doc.getDocumentElement().getChildNodes();
DOMSource source = null;
for(int x = 0;x < nl.getLength();x++)
{
Node e = nl.item(x);
if(e instanceof Element)
{
source = new DOMSource(e);
break;
}
}
transformer.transform(source, result);
System.out.println(sw.toString());
}
}
See this question with other possible answers.