How to update multiple nodes in xml in Java - java

I am trying to update multiple nodes in xml using nodelist. I am able to do it but i don't think my code is efficient. For updating two nodes I am repeating my code twice. I dont know how to loop it. I tried it from for loop, or tried making it an arraylist and everything but it is not working at all.
Here is my code:
String expressionDisclosure = "/DOCUMENT/ishobject/ishfields/ishfield[#name='FHPIDISCLOSURELEVEL']";
String expressionLanguage = "/DOCUMENT/ishobject/ishfields/ishfield[#name='DOC-LANGUAGE']";
String key = "";
String value = "";
try {
DocumentBuilderFactory documentbuilderfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentbuilder = documentbuilderfactory.newDocumentBuilder();
Document doc = documentbuilder.parse(filepath);
XPath xPath = XPathFactory.newInstance().newXPath();
Node updateNode = null;
NodeList nodelistLanguage = (NodeList) xPath.evaluate(expressionLanguage,
doc.getDocumentElement(), XPathConstants.NODESET);
NodeList nodelistDisclosure = (NodeList) xPath.evaluate(expressionDisclosure,
doc.getDocumentElement(), XPathConstants.NODESET);
key = nodelistLanguage.item(0).getTextContent();
if (key != null) {
value = getHashmap().get(key);
updateNode = nodelistLanguage.item(0);
updateNode.setTextContent(value);
}
key = nodelistDisclosure.item(0).getTextContent();
if (key != null) {
value = getHashmap().get(key);
updateNode = nodelistDisclosure.item(0);
updateNode.setTextContent(value);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult stream = new StreamResult(new File(filepath));
transformer.transform(source, stream);
} catch (Exception ex) {
ex.printStackTrace();
}
I am updating the node twice. Is this the proper way to do or can it be more efficient?

Related

How to update XML file value based on Key value using java

I'm trying to update xml file with system date in specific value based on key name,below is the sample xml file,here i want to update 10-25-2018 to present system date using java code,Please help me to achieve this.
<appSettings>
<add key="CommandTimeOut" value="7200"/>
<!--<add key="Bill" value="0"/>-->
<add key="Ism" value="1"/>
<add key="Cule" value="en-US"/>
<add key="Date" value="10-25-2018"/>
<add key="CreatedUser" value="SCHEDULER"/>
</appSettings>
Just try this code For updating your xml file .
public class XML_Parser {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("D:\\test.xml");
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//appSettings/add[#key]");
NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int c = 0; c < nl.getLength(); c++) {
Node currentItem = nl.item(c);
if (currentItem.getAttributes().getNamedItem("key").getNodeValue().equalsIgnoreCase("Date")) {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
currentItem.getAttributes().getNamedItem("value").setNodeValue(dateFormat.format(date));
}
}
doc.getDocumentElement().normalize();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("D:\\test.xml"));
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
System.out.println("XML file updated successfully");
} catch (Exception e) {
e.printStackTrace();
}
}
}

How to modify values of multiple XML tags?

I have been trying to modify values of more than one XML tag in java. So far I am able to get the values of the two nodes that I want to modify but while setting up values it always overrides the first one with the second one.
XML
<driver>
<BirthDate>1977-07-18</BirthDate>
<Age>40</Age>
<Gender>M</Gender>
<PrimaryResidence>OwnCondo</PrimaryResidence>
</driver>
I am trying to change Gender and PrimaryResidence tags.
Code
// Modifies multiple XML nodes
public static String changeCoreDiscountType(String reqXML) {
Document document = null;
String updatedXML = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(reqXML));
document = builder.parse(is);
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expression = xPath.compile("/driver/Gender | /driver/PrimaryResidence");
NodeList nodeList = (NodeList) expression.evaluate(document,XPathConstants.NODESET);
for(int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
node.setTextContent("F");
node.setTextContent("OwnCondo");
String value = node.getTextContent();
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new StringWriter());
transformer.transform(source, result);
updatedXML = result.getWriter().toString();
} catch (Exception ex) {
ex.printStackTrace();
}
return updatedXML;
}
Any help is appreciated.
You need to check you are updating the correct node first, e.g.
for(int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if(node.getNodeName() == "Gender")
node.setTextContent("F");
if(node.getNodeName() == "PrimaryResidence")
node.setTextContent("OwnCondo");
}
Full Demo

Retain escape character [" < etc..] while copying XML node - Java

I am creating target XML by copying source XML content. I am doing copy at node level.
Source XML has content with escape character which gets converted [$quot; to " etc...] while I create my target XML
Is there any way to retain original XML content.
Appreciate any help on this.
copyXmlFile("Workflow", "./Source.xml", "./Destination.xml");
private static void copyXmlFile(String xmlType, String objectSourceFile, String outfile) throws TransformerException {
//Get the DOM Builder Factory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//Get the DOM Builder
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
//document contains the complete XML as a Tree.
try {
File xmlFileContent = new File(objectSourceFile);
Document document = builder.parse(new FileInputStream(xmlFileContent));
// root elements
Document documentOut = builder.newDocument();
Element rootElementOut = documentOut.createElement(xmlType);
rootElementOut.setAttribute("xmlns", "http://soap.sforce.com/2006/04/metadata");
documentOut.appendChild(rootElementOut);
NodeList nodeList = document.getDocumentElement().getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node instanceof Element) {
//Node copiedNode = documentOut.importNode(node, true);
//rootElementOut.appendChild(copiedNode);
rootElementOut.appendChild(documentOut.adoptNode(node.cloneNode(true)));
}
}
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(documentOut);
//StreamResult result = new StreamResult(new File(outfile));
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
//transformer.setOutputProperty(OutputKeys.METHOD, "xml");
//transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(source, result);
System.out.println("Escaped XML String in Java: " + writer.toString());
} catch (SAXException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

Append to XML file

I am writing a Java application with a method to save data to XML.
Here is my code:
private void SaveToXML(String strCity, String strDate, String strforecast, String strminDegrees, String FileName)
{
try
{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("Weather");
doc.appendChild(rootElement);
Element weatherElement = doc.createElement(strCity);
rootElement.appendChild(weatherElement);
Element dateElement = doc.createElement("Date");
weatherElement.appendChild(dateElement);
Attr attr = doc.createAttribute("id");
attr.setValue(strDate);
dateElement.setAttributeNode(attr);
Element forecast = doc.createElement("forecast");
forecast.appendChild(doc.createTextNode(strforecast));
dateElement.appendChild(forecast);
Element mindegrees = doc.createElement("mindegrees");
mindegrees.appendChild(doc.createTextNode(strminDegrees));
dateElement.appendChild(mindegrees);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(FileName));
transformer.transform(source, result);
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
}
}
Method call:
SaveToXML("Auckland", "24-05-2013", "Fine", "10", "Test.xml");
Here is the output XML data:
<?xml version="1.0" encoding="UTF-8"?>
<Weather>
<Auckland>
<Date id="24-05-2013">
<forecast>Fine</forecast>
<mindegrees>10</mindegrees>
</Date>
</Auckland>
</Weather>
Can I please have some help to modify the code so that data is appended to the document in the correct element when the method is called.
E.g, If the method is called a second time with the City of Auckland, the weather details will be placed in the Auckland element. If a City is passed as a parameter that is not already in the document, a new element for that City will be created.
UPDATE2
This is my current code that performs an error:
private void SaveToXML(String strCity, String strDate, String strforecast, String strminDegrees, String FileName)
{
try
{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
//Document doc = docBuilder.newDocument();
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(FileName));
Element rootElement = doc.createElement("Weather");
doc.appendChild(rootElement);
NodeList weatherNodes = rootElement.getElementsByTagName(strCity);// do we already have node?
Element weatherElement;
if(weatherNodes.getLength() > 0){ // if so reuse
weatherElement = (Element) weatherNodes.item(0);
System.out.println("Found");
}else { // else create
weatherElement = doc.createElement(strCity);
rootElement.appendChild(weatherElement);
}
Element dateElement = doc.createElement("Date");
weatherElement.appendChild(dateElement);
Attr attr = doc.createAttribute("id");
attr.setValue(strDate);
dateElement.setAttributeNode(attr);
Element forecast = doc.createElement("forecast");
forecast.appendChild(doc.createTextNode(strforecast));
dateElement.appendChild(forecast);
Element mindegrees = doc.createElement("mindegrees");
mindegrees.appendChild(doc.createTextNode(strminDegrees));
dateElement.appendChild(mindegrees);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(FileName));
transformer.transform(source, result);
} catch (Exception ex) {
ex.printStackTrace();
}
}
The above code generates this error at runtime:
[Fatal Error] Test.xml:1:177: The markup in the document following the root element must be well-formed.
org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.
UPDATE3
Here is the code that is working:
private void SaveToXML(String strCity, String strDate, String strforecast, String strminDegrees, String FileName)
{
try
{
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc;
File file = new File(FileName);
if (!file.exists()) {
doc = docBuilder.newDocument();
doc.appendChild(doc.createElement("Weather"));
} else {
doc = docBuilder.parse(new File(FileName));
}
Element rootElement = doc.getDocumentElement();
Element weatherElement;
NodeList weatherNodes = doc.getDocumentElement().getElementsByTagName(strCity);
if (weatherNodes.getLength() > 0) {
weatherElement = (Element) weatherNodes.item(0);
} else {
weatherElement = doc.createElement(strCity);
rootElement.appendChild(weatherElement);
}
Element dateElement = doc.createElement("Date");
weatherElement.appendChild(dateElement);
Attr attr = doc.createAttribute("id");
attr.setValue(strDate);
dateElement.setAttributeNode(attr);
Element forecast = doc.createElement("forecast");
forecast.appendChild(doc.createTextNode(strforecast));
dateElement.appendChild(forecast);
Element mindegrees = doc.createElement("mindegrees");
mindegrees.appendChild(doc.createTextNode(strminDegrees));
dateElement.appendChild(mindegrees);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(FileName));
transformer.transform(source, result);
} catch (Exception ex) {
ex.printStackTrace();
}
}
To modify how you update the document structure for DOM,
modify
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("Weather");
doc.appendChild(rootElement);
Element weatherElement = doc.createElement(strCity);
rootElement.appendChild(weatherElement);
to
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("Weather");
doc.appendChild(rootElement);
NodeList weatherNodes = rootElement.getElementsByTagName(strCity);// do we already have node?
Element weatherElement;
if(weatherNodes.getLength() > 0){ // if so reuse
weatherElement = (Element) weatherNodes.item(0);
}else { // else create
weatherElement = doc.createElement(strCity);
rootElement.appendChild(weatherElement);
}
Be aware the DOM is really intended for small documents if this is going to get very large
you will need to look at something like STaX.
If XML file already exists you should parse it and update the city if it already exists or add otherwise. Then rewrite XML.
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc;
File file = new File(FileName);
if (!file.exists()) {
doc = docBuilder.newDocument();
doc.appendChild(doc.createElement("Weather"));
} else {
doc = docBuilder.parse(file);
}
Element rootElement = doc.getDocumentElement();
Element weatherElement = createWeatherElement(strCity, strDate, strforecast, strminDegrees, doc);
NodeList weatherNodes = doc.getDocumentElement().getElementsByTagName(strCity);
if (weatherNodes.getLength() > 0) {
rootElement.replaceChild(weatherElement, weatherNodes.item(0));
} else {
rootElement.appendChild(weatherElement);
}
Transformer transformer = transformerFactory.newTransformer();
...
private Element createWeatherElement(String strCity, String strDate, String strforecast, String strminDegrees, Document doc) {
Element rootElement = doc.getDocumentElement();
Element weatherElement = doc.createElement(strCity);
...
return weatherElement;
}

delete the unwanted strings before and after the string in xml file

xml file content
<distributionChannels><distributionChannel type="Wap" id="1"><contentChannelRefs>
<contentChannelRef id="2"><categories><category
link="http://images/11.gif" id="1"><names><name lang="de">Top Downloads</name><name
lang="ww">Tops</name></names></category></categories></contentChannelRef>
</contentChannelRefs></distributionChannel>
</distributionChannels>
how do i delete the unwanted content which i am reading from an xml file and the output should look as shown below:
<category link="http://images/11.gif" id="1"><names><name lang="de">Top Downloads</name><name lang="ww">Tops</name></names></category>
Reliable solution - use an XML parser. Simple solution is
s = s.substring(s.indexOf("<categories>"), s.indexOf("</categories>") + 13);
if you want to read categories one by one use regex
Matcher m = Pattern.compile("<category.*?>.*?</category>").matcher(xml);
for(int i = 0; m.find(); i++) {
System.out.println(m.group());
}
Pattern matching with XML is not recommended. Use a parser to get your nodes and the manage them accordingly. If you are interested in printing them I have included code to print the nodes.
public static void main(String[] args)
throws ParserConfigurationException, SAXException,
IOException, XPathExpressionException {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(s)));
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr
= xpath.compile("//categories//category");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
//This is where you are printing things. You can handle differently if
//you would like.
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodeToString(nodes.item(i)));
}
}
private static String nodeToString(Node node) {
StringWriter sw = new StringWriter();
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(new DOMSource(node), new StreamResult(sw));
} catch (TransformerException te) {
te.printStackTrace();
}
return sw.toString();
}

Categories

Resources