I am currently working on a xml project. So far, I have successfully link my xml to my java class using Dom Parser. I have the code provide below. What I am struggling with is updating my startdate's month by one so something like this 2/1/2013, 3/1/2013... will change in the xml file accordingly. I have the method call updateDate
at the bottom, but the xml file won't update it's value when I call it. Help will be appreciated
data.xml before
<?xml version="1.0" encoding="UTF-8">
<data>
<username>hello123</username>
<startdate>01/01/2011</startdate>
<enddate>06/01/2013</enddate>
</data>
desire data.xml after
<?xml version="1.0" encoding="UTF-8">
<data>
<username>hello123</username>
<startdate>02/01/2011</startdate> <--- This will change
<enddate>06/01/2013</enddate>
</data>
main.java
public class main {
public static void main(String[] args) {
Calendar cal2 = null;
String username = null;
String startdate = null;
String enddate = null;
String date = null;
String date_end = null;
try {
File data = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(data);
doc.getDocumentElement().normalize();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
username = getValue("username", element);
startdate = getValue("startdate", element);
enddate = getValue("enddate", element);
}
}
date = startdate;
//end date
Date date_end = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(enddate);
Calendar end_date_cal = Calendar.getInstance();
end_date_cal.setTime(date_end);
// initial date
Date date_int = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(date);
cal2 = Calendar.getInstance();
cal2.setTime(date_int);
//call the method
updateDate(cal2);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("data.xml"));
transformer.transform(source, result);
System.out.println("Update Successfully");
}
} catch (Exception ex) {
log.error(ex.getMessage());
ex.printStackTrace();
}
}
private static void updateDate(Calendar cal2){
cal2.add(Calendar.MONTH, 1);
//need to push it back to the calendar
}
private static String getValue(String tag, Element element) {
NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
Node node = (Node) nodes.item(0);
return node.getNodeValue();
}
private static void setValue(String tag, Element element , String input) {
NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
Node node = (Node) nodes.item(0);
node.setTextContent(input);
}
}
The way to change the value of an attribute, is to change its text value. This can be done using the setAttribute() method or setting the nodeValue property of the attribute node.
The nodeValue property is used to get the text value of a node. The getAttribute() method returns the value of an attribute.
Add a Node - appendChild() The appendChild() method adds a child node to an existing node. The new node is added (appended) after any existing child nodes. Note: Use insertBefore() if the position of the node is important.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy");
LocalDate ld = LocalDate.parse("2/1/2013", formatter);
System.out.println("From " + formatter.format(ld));
ld = ld.plusMonths(1);
System.out.println("To " + formatter.format(ld));
Which prints
From 2/1/2013
To 3/1/2013
BUT, you never apply the value back to the XML document. As I tried to demonstrate in your previous question, you need to change the textContent
of the node...
node.setTextContent(formatter.format(ld))
which is why I suggested using xPath instead of walking the document content
For example...
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
public class UpdateXML {
public static void main(String[] args) {
try {
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
DocumentBuilder b = f.newDocumentBuilder();
Document doc = b.parse(new File("Data.xml"));
XPath xPath = XPathFactory.newInstance().newXPath();
Node startDateNode = (Node) xPath.compile("/data/startdate").evaluate(doc, XPathConstants.NODE);
startDateNode.setTextContent(addMonthTo(startDateNode.getTextContent()));
xPath = XPathFactory.newInstance().newXPath();
Node endDateNode = (Node) xPath.compile("/data/enddate").evaluate(doc, XPathConstants.NODE);
endDateNode.setTextContent(addMonthTo(endDateNode.getTextContent()));
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");
DOMSource domSource = new DOMSource(doc);
StreamResult sr = new StreamResult(new File("AData.xml"));
tf.transform(domSource, sr);
} catch (ParserConfigurationException | SAXException | IOException | XPathExpressionException | DOMException | TransformerFactoryConfigurationError | IllegalArgumentException | TransformerException exp) {
exp.printStackTrace();
}
}
public static String addMonthTo(String value) {
String patterns[] = {"M/d/yyyy", "M/dd/yyyy", "MM/d/yyyy", "MM/dd/yyyy"};
LocalDate ld = null;
for (String pattern : patterns) {
try {
ld = LocalDate.parse(value, DateTimeFormatter.ofPattern(pattern));
break;
} catch (DateTimeParseException exp) {
}
}
if (ld == null) {
throw new DateTimeParseException("Could not parse " + value + " with available patterns", value, -1);
}
ld = ld.plusMonths(1);
return DateTimeFormatter.ofPattern("MM/dd/yyyy").format(ld);
}
}
Which took...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data>
<username>admin</username>
<password>12345</password>
<interval>1</interval>
<timeout>90</timeout>
<startdate>1/1/2013</startdate>
<enddate>06/01/2013</enddate>
<ttime>1110</ttime>
</data>
And outputted...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data>
<username>admin</username>
<password>12345</password>
<interval>1</interval>
<timeout>90</timeout>
<startdate>02/01/2013</startdate>
<enddate>07/01/2013</enddate>
<ttime>1110</ttime>
</data>
i want the startdate 6 months earlier then the enddate
String endDateValue = "07/01/2013";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
LocalDate endDate = LocalDate.parse(endDateValue, formatter);
LocalDate startDate = endDate.minusMonths(6);
String startDateValue = formatter.format(startDate);
I'd prefer Joda-Time, but
String endDateValue = "07/01/2013";
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
Date endDate = sdf.parse(endDateValue);
Calendar cal = Calendar.getInstance();
cal.setTime(endDate);
cal.add(Calendar.MONTH, -6);
Date startDate = cal.getTime();
String startDateVaue = sdf.format(startDate);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With