How to generate a xml file into a loop method? - java

I want to create a xml file and I've seen this example (https://www.mkyong.com/java/how-to-create-xml-file-in-java-dom/) however, I want to generate it inside a loop method.
<company>
<staff id="1">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</staff>
<staff id="2">
<firstname>hif</firstname>
<lastname>kiuk kim</lastname>
<nickname>gonuy</nickname>
<salary>50000</salary>
</staff>
</company>
But, using the code:
public void printXml(String firstName, String lastName, String nickname, String salary) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("company");
doc.appendChild(rootElement);
// staff elements
Element staff = doc.createElement("Staff");
rootElement.appendChild(staff);
// set attribute to staff element
Attr attr = doc.createAttribute("id");
attr.setValue("1");
staff.setAttributeNode(attr);
// shorten way
// staff.setAttribute("id", "1");
// firstname elements
Element firstnameElement = doc.createElement("firstname");
firstnameElement.appendChild(doc.createTextNode(firstName));
staff.appendChild(firstnameElement);
// lastname elements
Element lastnameElement = doc.createElement("lastname");
lastnameElement.appendChild(doc.createTextNode(lastName));
staff.appendChild(lastnameElement);
// nickname elements
Element nicknameElement = doc.createElement("nickname");
nicknameElement.appendChild(doc.createTextNode(nickname));
staff.appendChild(nicknameElement);
// salary elements
Element salaryElement = doc.createElement("salary");
salaryElement.appendChild(doc.createTextNode(salary));
staff.appendChild(salaryElement);
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("C:\\file.xml"));
// Output to console for testing
// StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
System.out.println("File saved!");
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
}
}
}
the information on the loop about the company staff is always being replaced and it save only the last info:
for (Staff staff: staffList){
String firstName = staff.getFirstName();
String lastName = staff.getLastName();
String nickname = staff.getNickname ();
double salary = staff.getSalary();
printXml(firstName, lastName, nickname, salary);
<company>
<staff id="2">
<firstname>hif</firstname>
<lastname>kiuk kim</lastname>
<nickname>gonuy</nickname>
<salary>50000</salary>
</staff>
</company>
How can I save all info that I get during the loop? Thank you.

Your'e overwriting the file instead of appending to it.
You should initialize StreamResult with a stream that can write to a file as well as append to it.
For example, you can use FileOutputStream, and pass true for its constructor for appending.
However, you need to close the stream, so one option would be changing your code so that printXml would become getXml, and your code would then look as follows:
FileOutputStream stream = new FileOutputStream("C:\\file.xml", true);
StreamResult result = new StreamResult(stream);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
for (Staff staff: staffList){
DOMSource source = getXml(staff); // call staff's getters inside getXml
transformer.transform(source, result);
}
stream.close();
(You should also move lines 3-4 above to a method named getTransformer).

Related

Root element shouldn't be repeat and, the child nodes only needed to be appended in XML Dom Parser

After form submission, the values are to be stored in an XML file. (XML Dom PArser)
Below given the program which I tried to do the same.
public void writeXMLfile(ApplyLieuDto lieuDto) {
String satDte =
Util.convertUtilDateToString(lieuDto.getSatDutyDteUtil());
//String satDteAMPM = lieuDto.getSatDutyDteAmPm();
//String satDutyDte = satDte + satDteAMPM;
String offDte = Util.convertUtilDateToString(lieuDto.getOffDteUtil());
//String offDteAMPM = lieuDto.getOffDteAmPm();
//String offDate = offDte + offDteAMPM;
String modDate =
Util.convertUtilDateToString(lieuDto.getDateUpdateUtil());
String filePath = "file.xml";
try {
DocumentBuilderFactory docFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("lieu");
doc.appendChild(rootElement);
// staff elements
Element staff = doc.createElement("staff");
rootElement.appendChild(staff);
// set attribute to staff element
Attr attr = doc.createAttribute("id");
attr.setValue(lieuDto.getStaffId());
staff.setAttributeNode(attr);
// name elements
Element firstname = doc.createElement("name");
firstname.appendChild(doc.createTextNode(lieuDto.getName()));
staff.appendChild(firstname);
// contact number elements
Element contact = doc.createElement("contactnumber");
contact.appendChild(doc.createTextNode(lieuDto.getContact()));
staff.appendChild(contact);
// email elements
Element email = doc.createElement("email");
email.appendChild(doc.createTextNode(lieuDto.getEmail()));
staff.appendChild(email);
// satdutydate elements
Element satDutyDate = doc.createElement("satDte");
satDutyDate.appendChild(doc.createTextNode(satDte));
staff.appendChild(satDutyDate);
// satdutydateAMPM elements
Element satDutyDateAMPM = doc.createElement("satDteAMPM");
satDutyDateAMPM.appendChild(doc.createTextNode
(lieuDto.getSatDutyDteAmPm()));
staff.appendChild(satDutyDateAMPM);
// offDate elements
Element offDat = doc.createElement("offdate");
offDat.appendChild(doc.createTextNode(offDte));
staff.appendChild(offDat);
// offDateAMPM elements
Element offDatAMPM = doc.createElement("offdateAMPM");
offDatAMPM.appendChild(doc.createTextNode(lieuDto.getOffDteAmPm()));
staff.appendChild(offDatAMPM);
// appOfficer elements
Element appOfficer = doc.createElement("approvingofficer");
appOfficer.appendChild(doc.createTextNode
(lieuDto.getApprovingOfficer()));
staff.appendChild(appOfficer);
// Date elements
Element modifieddate = doc.createElement("modifieddate");
modifieddate.appendChild(doc.createTextNode(modDate));
staff.appendChild(modifieddate);
// status elements
Element status = doc.createElement("status");
status.appendChild(doc.createTextNode(lieuDto.getStatus()));
staff.appendChild(status);
// write the content into xml file
TransformerFactory transformerFactory =
TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new
FileWriter(filePath,true));
// Output to console for testing
StreamResult strmResult = new StreamResult(System.out);
transformer.transform(source, result);
transformer.transform(source, strmResult);
System.out.println("File saved!");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
The output I got as something like this below
<company>
<staff id="1">
<firstname>Priya</firstname>
<lastname>Rajan</lastname>
<salary>100000</salary>
</staff>
</company>
<company>
<staff id="2">
<firstname>Peter</firstname>
<lastname>Jas</lastname>
<salary>100000</salary>
</staff>
</company>
But, the expected result is
<company>
<staff id="1">
<firstname>Priya</firstname>
<lastname>Rajan</lastname>
<salary>100000</salary>
</staff>
<staff id="2">
<firstname>Peter</firstname>
<lastname>Jas</lastname>
<salary>100000</salary>
</staff>
</company>
Root element shouldn't be repeat and, the child nodes only needed to be appended.
Please help me on this.
Thanks.
I got the answer. `
public boolean writeXMLfile(ApplyLieuDto lieuDto)
{
boolean isAdded = false;
String filePath = "file.xml";
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
try {
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.parse(filePath);
NodeList oldList = doc.getElementsByTagName("staff");
int oldListCount = oldList.getLength();
System.out.println("Old List Count Value :: "+oldListCount);
Element root = doc.getDocumentElement();
Element rootElement = doc.getDocumentElement();
Collection<ApplyLieuDto> svr = new ArrayList<ApplyLieuDto>();
svr.add(lieuDto);
for(ApplyLieuDto lieu : svr)
{
Element staff = doc.createElement("staff");
rootElement.appendChild(staff);
// set attribute to staff element
Attr attr = doc.createAttribute("id");
attr.setValue(lieu.getStaffId());
staff.setAttributeNode(attr);
Element firstname = doc.createElement("name");
firstname.appendChild(doc.createTextNode(lieu.getName()));
staff.appendChild(firstname);
// contact number elements
Element contact = doc.createElement("contactnumber");
contact.appendChild(doc.createTextNode(lieu.getContact()));
staff.appendChild(contact);
// email elements
Element email = doc.createElement("email");
email.appendChild(doc.createTextNode(lieu.getEmail()));
staff.appendChild(email);
String satDte = Util.convertUtilDateToString(lieu.getSatDutyDteUtil());
// satdutydate elements
Element satDutyDate = doc.createElement("satDte");
satDutyDate.appendChild(doc.createTextNode(satDte));
staff.appendChild(satDutyDate);
// satdutydateAMPM elements
Element satDutyDateAMPM = doc.createElement("satDteAMPM");
satDutyDateAMPM.appendChild(doc.createTextNode(lieu.getSatDutyDteAmPm()));
staff.appendChild(satDutyDateAMPM);
String offDte = Util.convertUtilDateToString(lieu.getOffDteUtil());
// offDate elements
Element offDat = doc.createElement("offdate");
offDat.appendChild(doc.createTextNode(offDte));
staff.appendChild(offDat);
// offDateAMPM elements
Element offDatAMPM = doc.createElement("offdateAMPM");
offDatAMPM.appendChild(doc.createTextNode(lieu.getOffDteAmPm()));
staff.appendChild(offDatAMPM);
// appOfficer elements
Element appOfficer = doc.createElement("approvingofficer");
appOfficer.appendChild(doc.createTextNode(lieu.getApprovingOfficer()));
staff.appendChild(appOfficer);
String modDate = Util.convertUtilDateToString(lieu.getDateUpdateUtil());
// Date elements
Element modifieddate = doc.createElement("modifieddate");
modifieddate.appendChild(doc.createTextNode(modDate));
staff.appendChild(modifieddate);
// status elements
Element status = doc.createElement("status");
status.appendChild(doc.createTextNode(lieu.getStatus()));
staff.appendChild(status);
root.appendChild(staff);
}
DOMSource source = new DOMSource(doc);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
StreamResult result = new StreamResult(filePath);
StreamResult strmResult = new StreamResult(System.out);
transformer.transform(source, result);
transformer.transform(source, strmResult);
NodeList newList = doc.getElementsByTagName("staff");
int newListCount = newList.getLength();
System.out.println("New List Count Value :: "+newListCount);
if(newListCount > oldListCount)
{
isAdded = true;
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
return isAdded;
}
`

Remove Namespace from tag

I searched in SO but I did not found nothing that solves my problem. I hope some one can help me.
I am building a XML file and I need to remove the Namespace xmlns.
That is my code
Document xmlDocument = new Document();
Namespace ns1 = Namespace.getNamespace("urn:iso:std:iso:20022:tech:xsd:pain.001.001.03");
Namespace ns2 = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Element root = new Element("Document", ns1);
root.addNamespaceDeclaration(ns2);
xmlDocument.setRootElement(root);
Element CstmrCdtTrfInitn = new Element("CstmrCdtTrfInitn");
root.addContent(CstmrCdtTrfInitn);
PrintDocumentHandler pdh = new PrintDocumentHandler();
pdh.setXmlDocument(xmlDocument);
request.getSession(false).setAttribute("pdh", pdh);
ByteArrayOutputStream sos = new ByteArrayOutputStream();
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
Format format = outputter.getFormat();
format.setEncoding(SOPConstants.ENCODING_SCHEMA);
outputter.setFormat(format);
outputter.output(root, sos);
sos.flush();
return sos;
And this is the created XML-File
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn xmlns=""/>
</Document>
I have to remove the namespace xmlns from the tag CstmrCdtTrfInitn.
Many thanks in advance.
Namespace declaration without prefix (xmlns="...") is known as default namespace. Notice that, unlike prefixed namespace, descendant elements without prefix inherit ancestor's default namespace implicitly. So in the XML below, <CstmrCdtTrfInitn> is considered in the namespace urn:iso:std:iso:20022:tech:xsd:pain.001.001.03 :
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn/>
</Document>
If this is the wanted result, instead of trying to remove xmlns="" later, you should try to create CstmrCdtTrfInitn using the same namespace as Document in the first place :
Element CstmrCdtTrfInitn = new Element("CstmrCdtTrfInitn", ns1);
I did some code for you, I dont know what package You are using... If You only want to remove the xmlns attribute from the CstmrCdtTrfInitn tag try with this code as other method to generate XML (I just modified this):
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("Document");
rootElement.setAttribute("xmlns", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03");
rootElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
doc.appendChild(rootElement);
// staff elements
Element CstmrCdtTrfInitn = doc.createElement("CstmrCdtTrfInitn");
rootElement.appendChild(CstmrCdtTrfInitn);
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
// Output to console for testing
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
}

How to add namespace prefix in Java DOM XML builder

I need to set prefix of the element in my xml. I need to print the xml in the format below:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<cars xmlns:dcterms="http://purl.org/dc/terms/" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<supercars company="Ferrari">
<dcterms:carname type="formula one">Ferrari 101</dcterms:carname>
<msxsl:carname type="sports">Ferrari 202</msxsl:carname>
</supercars>
</cars>
However, I am not able to add the prefix in my XML. What I am getting is this.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<cars xmlns:dcterms="http://purl.org/dc/terms/" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<supercars company="Ferrari">
<carname type="formula one">Ferrari 101</carname>
<carname type="sports">Ferrari 202</carname>
</supercars>
</cars>
Following is my Java Code:
public static void main(String args[]) {
try {
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder =
dbFactory.newDocumentBuilder();
Document doc = dBuilder.newDocument();
// root element
Element rootElement = doc.createElement("cars");
rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:dcterms", "http://purl.org/dc/terms/");
rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:msxsl", "urn:schemas-microsoft-com:xslt");
doc.appendChild(rootElement);
// supercars element
Element supercar = doc.createElement("supercars");
rootElement.appendChild(supercar);
// setting attribute to element
Attr attr = doc.createAttribute("company");
attr.setValue("Ferrari");
// supercar.setAttributeNodeNS(attr);
supercar.setAttributeNode(attr);
// carname element
Element carname = doc.createElement("carname");
Attr attrType = doc.createAttribute("type");
attrType.setValue("formula one");
carname.setAttributeNode(attrType);
carname.appendChild(
doc.createTextNode("Ferrari 101"));
supercar.appendChild(carname);
Element carname1 = doc.createElement("carname");
Attr attrType1 = doc.createAttribute("type");
attrType1.setValue("sports");
carname1.setAttributeNode(attrType1);
carname1.appendChild(
doc.createTextNode("Ferrari 202"));
supercar.appendChild(carname1);
// write the content into xml file
TransformerFactory transformerFactory =
TransformerFactory.newInstance();
Transformer transformer =
transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
StreamResult result =
new StreamResult(new File("cars.xml"));
transformer.transform(source, result);
// Output to console for testing
StreamResult consoleResult =
new StreamResult(System.out);
transformer.transform(source, consoleResult);
} catch (Exception e) {
e.printStackTrace();
}
}
}
And I checked this link Adding namespace prefix XML String using XML DOM. However, this only talks about the SAX way of doing thing. I need to do this in DOM.
I tried setPrefix method and it is throwing me NAMESPACE_ERR
First of all, make sure you set dbFactory.setNamespaceAware(true);, if you want to work with a DOM supporting namespaces.
Then use createElementNS, e.g. Element carname = doc.createElementNS("http://purl.org/dc/terms/", "dcterms:carname");, to create elements in a namespace. Use the same approach for the element in the other namespace.

How to reposition a node in XML with DOM?

So I have this wich should put into an xml file a movie.
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse("D:\\College\\Java Eclipse\\tema5\\Movies\\Movies.xml");
try {
Element rootElement = doc.createElement("Movie");
doc.appendChild(rootElement);
// firstname elements
Element id = doc.createElement("Id");
id.appendChild(doc.createTextNode("3"));
rootElement.appendChild(id);
// lastname elements
Element name = doc.createElement("Name");
name.appendChild(doc.createTextNode("Movie 3"));
rootElement.appendChild(name);
// nickname elements
Element category = doc.createElement("Category");
category.appendChild(doc.createTextNode("Animation"));
rootElement.appendChild(category);
// salary elements
Element releasedate = doc.createElement("ReleaseDate");
releasedate.appendChild(doc.createTextNode("10-Jun-2012"));
rootElement.appendChild(releasedate);
Element rating = doc.createElement("Rating");
rating.appendChild(doc.createTextNode("10"));
rootElement.appendChild(rating);
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("D:\\College\\Java Eclipse\\tema5\\Movies\\Movies.xml"));
// Output to console for testing
// StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
} catch (TransformerException tfe) {
tfe.printStackTrace();
}
The problem is that in my xml file I already have two movies, when it tries to put the third one it succeeds but at the forth one it dies. I think it's because of the nodes and I want to know how to reposition the last to the end of the file so I can place more movies. This is the xml doc after the first insertion.
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Movie>
<Movie>
<Id>1</Id>
<Name>Movie 1</Name>
<Category>Action</Category>
<ReleaseDate>22-JUN-2010</ReleaseDate>
<Rating>9</Rating>
</Movie>
<Movie>
<Id>2</Id>
<Name>Movie 2</Name>
<Category>Comedy</Category>
<ReleaseDate>2-JUN-2011</ReleaseDate>
<Rating>8</Rating>
</Movie>
</Movie>
<Movie>
<Id>3</Id>
<Name>Movie 3</Name>
<Category>Animation</Category>
<ReleaseDate>10-Jun-2012</ReleaseDate>
<Rating>10</Rating>
</Movie>
Element docRoot = doc.getDocumentElement();
Element rootElement = doc.createElement("Movie");
docRoot.appendChild(rootElement);
I would suggest renaming your rootElement variable to newMovie as it is missleading. You can only have one root element in xml, and you get it by doc.getDocumentElement()

Java xml saver optimization

I have a colection of objects organised in trees that i want to save as a XML file, but i want to do this as optimally as i can. I use somehing like this (see the code) to do it, but i would appeciate if someone could tell me a better way of doing it :
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("company");
doc.appendChild(rootElement);
Element staff = doc.createElement("Staff");
rootElement.appendChild(staff);
Attr attr = doc.createAttribute("id");
attr.setValue("1");
staff.setAttributeNode(attr);
Element firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode("yong"));
staff.appendChild(firstname);
Element lastname = doc.createElement("lastname");
lastname.appendChild(doc.createTextNode("mook kim"));
staff.appendChild(lastname);
Element nickname = doc.createElement("nickname");
nickname.appendChild(doc.createTextNode("mkyong"));
staff.appendChild(nickname);
Element salary = doc.createElement("salary");
salary.appendChild(doc.createTextNode("100000"));
staff.appendChild(salary);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("C:\\file.xml"));
transformer.transform(source, result);
The shot answer is: use JAXB
In case of using it, you can put annotation such as #XmlElement on your fields and classes to serialize/deserialize them to XML seamlessly. And it will handle all the recursion in your tree without any problems.

Categories