Java xml saver optimization - java

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.

Related

Fetching the XML without changing the order of the attributes

I am trying to fetch the xml from the file, but while fetching the order of the attributes are changing
I know it will not matter but in my case it does, as I am hashing the document
I am trying the below code but it is ordering the attributes in an alphabetical manner
File fXmlFile = new File("C:\\Users\\Desktop\\abc.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
String xml=writer.toString();
this is the xml that I am trying to read
in the variable xml, I am getting the xml with the attributes sorted in an alphabetical order
Attribute order has no meaning in XML, and tools that process XML are at liberty to change the order.
When you are comparing documents for equivalence (which you appear to be doing) then you should use comparison and hash functions that do not depend on the order of attributes.

how to add new node under a specific node in dom4j JAVA

I want to generate flexiField tags and add it to current xml file.
Here is My xmlFile.
<com.model.FlexiFieldList>
<flexiFields>
<flexiField>
<fieldDesc>BL</fieldDesc>
<fieldName>BL</fieldName>
<fieldType>FREE_TEXT</fieldType>
<fieldTypeDataStr/>
<sensitive>false</sensitive>
<value>True</value>
<valueType>String</valueType>
</flexiField>
</flexiFields>
</com.model.FlexiFieldList>
I want to add new flexiField and I have this Java Code but When I run my code, it adds flexiField node under <com.model.FlexiFieldList> element
I know that in Element root = document.getDocumentElement(); part we show that we will add new node to root location but I couldnt find any way to change it
Actually My question is that how can I change root path so when I run root.appendChild(newFlexiField); it will add new flexiField node under flexiFields node
File file = new File("C:/Users/xxx/Desktop/ff.xml");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(file);
Element root = document.getDocumentElement();
Collection<FlexiField> flexiFields = new ArrayList<FlexiField>();
flexiFields.add(new FlexiField());
for (FlexiField flexiField : flexiFields) {
// server elements
Element newFlexiField = document.createElement("flexiField");
Element name = document.createElement("fieldDesc");
name.appendChild(document.createTextNode(flexiField.fieldDesc()));
newFlexiField.appendChild(name);
Element port = document.createElement("fieldName");
port.appendChild(document.createTextNode(flexiField.fieldName()));
newFlexiField.appendChild(port);
root.appendChild(newFlexiField);
}
DOMSource source = new DOMSource(document);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
StreamResult result = new StreamResult(file);
transformer.transform(source, result);
Assumming you have only one <flexiFields> element in you xml file you can try this:
File file = new File("C:/Users/xxx/Desktop/ff.xml");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(file);
Element root = document.getDocumentElement();
// to print your root element
System.out.println("\n*************root************");
System.out.println(root.getNodeName());
// to find the flexiFields
Node firstChild=root.getFirstChild();
while (firstChild != null && firstChild.getNodeType() != Node.ELEMENT_NODE)
{
firstChild = firstChild.getNextSibling();
}
System.out.println(firstChild.getNodeName());
Collection<FlexiField> flexiFields = new ArrayList<FlexiField>();
flexiFields.add(new FlexiField());
for (FlexiField flexiField : flexiFields) {
// server elements
Element newFlexiField = document.createElement("flexiField");
Element name = document.createElement("fieldDesc");
name.appendChild(document.createTextNode(flexiField.fieldDesc()));
newFlexiField.appendChild(name);
Element port = document.createElement("fieldName");
port.appendChild(document.createTextNode(flexiField.fieldName()));
// append your child
newFlexiField.appendChild(port);
firstChild.appendChild(newFlexiField);
}
DOMSource source = new DOMSource(document);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
StreamResult result = new StreamResult(file);
transformer.transform(source, result);

Delete an xml Element and copy the same element in a new xml -- in java

I am having some problem in deleting and copying the same xml element. The problem is I have 2 xml files and after comparing both I want to delete the element(s) those are only in file1 and at the same copy I want to copy these elements in a newly generated xml. I can delete the elements but I am not able to copy them in another xml file.
Here is the code:
for (Map.Entry<String, Element> entry : Map1.entrySet()) {
String key = entry.getKey();
if (!Map2.containsKey(key)) {
Map1.remove(key);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc= builder.newDocument();
Element rootElement =
doc.createElementNS("", "missing");
doc.appendChild(rootElement);
//here i want to copy the deleted element in new xml file.
//rootElement.appendChild(Map1.get(key));
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult newXml = new StreamResult(new File("C:/user/desktop/Output.xml"));
transformer.transform(source, newXml);
}
}
Shift the part where Map1.remove(key); to the end of the code. Your rootElement.appendChild(Map1.get(key)) would not work because key is no longer in Map1 after you removed it.

Create namespace in dom element issue

Im trying to create XML document with DOM APi's and when i use the following code I got the
expect result
Element rootTreeNode = document.createElementNS("http://schemas.microsoft.com/ado/2007","ex" + ":Ex")
this is the output with tags in output console
ex:Ex Version="1.0" xmlns:ex="http://schemas.microsoft.com/ado/2007"/
Now I want to add to this element the following
**xmlns:gp**="http://www.pst.com/Protocols/Data/Generic"
and I dont succeed with the xmlns:gp i have tried to use
the like the following
rootTreeNode.setAttributeNS("xmlns" ,"gp","http://www.pst.com/Protocols/Data/Generic")
and i have got it like the folloing
**xmlns:ns0="xmlns"** **ns0:gp**="http://www.pst.com/Protocols/Data/Generic"
and if put null in the first parameter
rootTreeNode.setAttributeNS(null ,"gp","http://www.pst.com/Protocols/Data/Generic")
I get just gp with the URL without the xmlns .
what am i doing wrong here ?
Thanks!!!
Complete test:
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element root = doc.createElementNS("http://schemas.microsoft.com/ado/2007","ex" + ":Ex");
root.setAttributeNS("http://www.w3.org/2000/xmlns/" ,"xmlns:gp","http://www.pst.com/Protocols/Data/Generic");
doc.appendChild(root);
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(doc);
trans.transform(source, result);
String xmlString = sw.toString();
System.out.println("Xml:\n\n" + xmlString);

parsing the xml to get the root element and then add a tag dynamically under the root tag

I want to parse the xml file to get the root element. Then append add the tag named first-name under that root tag. How do I do this ? This is what I have been doing right now :
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Element blobKey_E = document.createElement("first-name");
blobKey_E.appendChild( document.createTextNode( name ) );
// NOW APPEND blobKey_E to the root element
// After getting the root element from the xml in some directory
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File("/home/non-admin/NetBeansProjects/Personal Site_Testers/web/xml/xml_1.xml"));
transformer.transform(source, result);
Element root = document.getDocumentElement();
root.appendChild(document.createElement("first-name"));
Will append first-name to the end of the DOM tree
Inserting into the first position is a little more difficult...
Element root = document.getDocumentElement();
if (root.hasChildNodes()) {
Node firstChild = root.getFirstChild();
root.insertBefore(document.createElement("first-name"), firstChild);
} else {
// Append to as per previous example
}
UPDATE
Eleement firstName = document.createElement("first-name");
firstName.setTextContent("Henry");

Categories