I am trying to convert an excel file into xml file in java.
try {
DocumentBuilderFactory dFact = DocumentBuilderFactory.newInstance();
DocumentBuilder build = dFact.newDocumentBuilder();
Document doc = build.newDocument();
Element root = doc.createElement("dataroot");
doc.appendChild(root);
Element Details = doc.createElement("DATA");
root.appendChild(Details);
for(int i=0; i<list.size()-2; i +=3 ) {
Element name = doc.createElement("Name");
name.appendChild(doc.createTextNode(String.valueOf(list.get(i))));
Details.appendChild(name);
Element id = doc.createElement("Empid");
id.appendChild(doc.createTextNode(String.valueOf(list.get(i+1))));
Details.appendChild(id);
Element ad = doc.createElement("Add");
ad.appendChild(doc.createTextNode(String.valueOf(list.get(i+2))));
Details.appendChild(ad);
Element mo = doc.createElement("Mobile");
mo.appendChild(doc.createTextNode(String.valueOf(list.get(i+3))));
Details.appendChild(mo);
}
// Save the document to the disk file
TransformerFactory tranFactory = TransformerFactory.newInstance();
Transformer aTransformer = tranFactory.newTransformer();
// format the XML nicely
aTransformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
aTransformer.setOutputProperty(
"{http://xml.apache.org/xslt}indent-amount", "4");
aTransformer.setOutputProperty(OutputKeys.INDENT, "yes");
This is my code for reading an ArrayList of excel data (with values and null) and convert it into xml.
my output is:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<dataroot generated="2015-04-26T10:52:27">
<DATA>
<Name>Rony</Name>
<Empid>FBL123</Empid>
<Add>Dhaka</Add>
<Mobile>12333333</Mobile>
</DATA>
<DATA>
<Name>12333333</Name>
<Empid>Azam</Empid>
<Add>FBL321</Add>
<Mobile>Dhaka</Mobile>
</DATA>
<DATA>
<Name>Dhaka</Name>
<Empid>67778888</Empid>
<Add>Rony</Add>
<Mobile>Chandpur</Mobile>
</DATA>
<DATA>
<Name>Chandpur</Name>
<Empid>099776655</Empid>
<Add>Azam</Add>
<Mobile>9988</Mobile>
</DATA>
</dataroot>
But my desired xml output is:
<?xml version="1.0" encoding="UTF-8"?>
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2015-04-26T10:52:27">
<DATA>
<Name>Rony</Name>
<Empid>FBL123</Empid>
<Add>Dhaka</Add>
<Mobile><Prop ID="Personal" ValStr="Mrs. YYYYYYYY " /><Prop ID="FAMILY" ValStr="Mrs. ZZZZZZZZ" />"</CLIENTPROP>
</DATA>
<DATA>
<Name>AZAM</Name>
<Empid>FBL321</Empid>
<Add>Dhaka</Add>
<Mobile><Prop ID="Personal" ValStr="Mrs. YYYYYYYY " /><Prop ID="FAMILY" ValStr="Mrs. ZZZZZZZZ" />"</CLIENTPROP>
</DATA>
</dataroot>
How i Can do it?
To have "DATA" tags, you shoud move the lines below into your for statement:
Element Details = doc.createElement("DATA");
root.appendChild(Details);
To add some property on "dataroot", use the code below:
root.setAttribute("generated", "2015-04-26T10:52:27");
On Mobile element, try this:
Element mo = doc.createElement("Mobile");
Element prop = doc.createElement("Prop");
prop.setAttribute("ID", "FAMILY");
prop.setAttribute("ValStr", "Mrs. YYYYYYYY");
Element prop2 = doc.createElement("Prop");
prop2.setAttribute("ID", "Personal");
prop2.setAttribute("ValStr", "Mrs. ZZZZZZZZ");
mo.appendChild(prop);
mo.appendChild(prop2);
Try to read about DOM parser on this tutorial as well. How to create XML file in Java – (DOM Parser)
Related
Currently I'm trying to develop some code with Java 9 and javax.xml libraries (both mandatory for my task) that edits an XML file and I'm having some weird issues adding child nodes.
This is the XML file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
</users>
and I want to edit it build something like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
<user>
<name>A name</name>
<last-name>Last Name</last-name>
<username>username</username>
</user>
</users>
Now, the first run of the code adds a single blank line before the <user> node. When it runs for a second time fills with more blank lines:
<users>
<user>
<name>name</name>
<last-name>lastname</last-name>
<username>username</username>
</user>
<user>
<name>name</name>
<last-name>lastname</last-name>
<username>username</username>
</user>
</users>
This is the XML generated after running the program 2 times. As you can see, it adds blank lines before the <user> nodes and between the other nodes, exactly n-1 blank lines between nodes being n the times the code was executed.
Wondering what is the content of those nodes before updating the file I wrote the next code:
int i=0;
while (root.getChildNodes().item(i)!=null){
Node aux = root.getChildNodes().item(i);
System.out.println("Node text content: ".concat(aux.getTextContent()));
i++;
}
1st execution:
Node text content:
Node text content: namelastnameusername
2nd execution:
Node text content:
Node text content:
name
lastname
username
Node text content:
Node text content: namelastnameusername
3rd execution
Node text content:
Node text content:
name
lastname
username
Node text content:
Node text content:
name
lastname
username
Node text content:
Node text content: namelastnameusername
Finally, this is the Java code:
private static void saveUser(String firstName, String lastName, String username){
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(databaseFile));
Element root = doc.getDocumentElement();
root.normalize();
// build user node
Element userNode = doc.createElement("user");
Element nameNode = doc.createElement("name");
Element lastNameNode = doc.createElement("last-name");
Element usernameNode = doc.createElement("username");
//build structure
nameNode.appendChild(doc.createTextNode(firstName));
lastNameNode.appendChild(doc.createTextNode(lastName));
usernameNode.appendChild(doc.createTextNode(username));
userNode.appendChild(nameNode);
userNode.appendChild(lastNameNode);
userNode.appendChild(usernameNode);
root.appendChild(userNode);
//write the updated document to file or console
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(databaseFile));
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
}catch (SAXException | ParserConfigurationException | IOException | TransformerException e1) {
e1.printStackTrace();
}
}
The only solution I could find is to delete blank lines after XML generation, but I think it's not a proper solution and I would like to find some alternatives first.
Any suggestions on how to tackle this problem?
I suspect it's the Transformer that's adding the blank lines.
Instead of using the default transformer (transformerFactory.newTransformer()), try passing in an XSLT that has xsl:strip-space set (transformerFactory.newTransformer(new StreamSource(new File(PATH_TO_XSLT_FILE)));)...
XSLT File
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
In Short: Actually, in Java 9, you may only take the way of deleting the blank line after xml generated or after xml parsed from file, like :
private void clearBlankLine(Element element) {
NodeList childNodes = element.getChildNodes();
for (int index = 0; index < childNodes.getLength(); index++) {
Node item = childNodes.item(index);
if (item.getNodeType() != 1 && System.lineSeparator()
.equals(item.getNodeValue())) {
element.removeChild(item);
} else {
if (item instanceof Element) {
clearBlankLine((Element) item);
}
}
}
}
Then invoke this with root element.
Details:
In the flow of xml generation, there are three lifecycle for each element parse: startElement,parse,endElement. While the indent feature is implemented in the startElement scope. Also the indent will add a blank line in document.
The invoke stack is different in java 8 between java 9:
In Java 8: ToStream#startElement-> ToStream#indent(IfNecessary)
In Java 9: ToStream#startElement->ToStream#flushCharactersBuffer(IfNecessary)->ToStream#indent(IfNecessary)
While the flushCharactersBuffer also do indent when we open the indent feature like: transformer.setOutputProperty(OutputKeys.INDENT, "yes"); Also the condition to invoke method: flushCharactersBuffer and method: indent almost same.
That means in Java 9, this would add two new line for each need indented element, result to blank lines appeared.
I found this solution using an XPath to be much cleaner than any of the others here (h/t to Isaac for his answer over at https://stackoverflow.com/a/12670194/1339923). It doesn't require a separate (i.e., XSLT) file, and doesn't require you to add 14 lines of Java to iterate over every node in the Document. Only 6 lines of code.
In the case of #pablo-r-grande's original question... right before this comment (i.e., just before loading the Document into the DOMSource):
//write the updated document to file or console
...I would add these lines:
// Generate list of all empty Nodes, them remove them
XPath xp = XPathFactory.newInstance().newXPath();
NodeList nl = (NodeList) xp.evaluate("//text()[normalize-space(.)='']", doc, XPathConstants.NODESET);
for (int i = 0; i < nl.getLength(); ++i) { // note the position of the '++'
Node node = nl.item(i);
node.getParentNode().removeChild(node);
}
your solution and below suggestion are both works fine for me, please try with this test case,
public static void main(String[] args) {
saveUser("test one", "test two", "test three");
}
private static void saveUser(String firstName, String lastName, String username){
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("second.xml"));
Element root = doc.getDocumentElement();
root.normalize();
// build user node
Element userNode = doc.createElement("user");
Element nameNode = doc.createElement("name");
Element lastNameNode = doc.createElement("last-name");
Element usernameNode = doc.createElement("username");
userNode.appendChild(nameNode).setTextContent(firstName); //set the text content
userNode.appendChild(lastNameNode).setTextContent(lastName);
userNode.appendChild(usernameNode).setTextContent(username);
root.appendChild(userNode);
//write the updated document to file or console
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("second.xml"));
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
}catch (Exception e) {
e.printStackTrace();
}
}
second.xml (before execution)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
</users>
second.xml (first execution)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
<user>
<name>test one</name>
<last-name>test two</last-name>
<username>test three</username>
</user>
</users>
second.xml (second execution)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
<user>
<name>test one</name>
<last-name>test two</last-name>
<username>test three</username>
</user>
<user>
<name>test one</name>
<last-name>test two</last-name>
<username>test three</username>
</user>
</users>
second.xml (third execution)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
<user>
<name>test one</name>
<last-name>test two</last-name>
<username>test three</username>
</user>
<user>
<name>test one</name>
<last-name>test two</last-name>
<username>test three</username>
</user>
<user>
<name>test one</name>
<last-name>test two</last-name>
<username>test three</username>
</user>
</users>
importing classes,
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.parsers.DocumentBuilder; // missing import class
import org.w3c.dom.Document;
import org.w3c.dom.Element;
I'm generating this XML:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap xmlns="" id="0">
<loc>http://x.ae/sitemap-url/ae/sitemap-index.xml</loc>
<lastmod>2015-02-19</lastmod>
</sitemap>
<sitemap xmlns="" id="1">
<loc>http://x.bh/sitemap-url/bh/sitemap-index.xml</loc>
<lastmod>2015-02-19</lastmod>
</sitemap>
<sitemap xmlns="" id="2">
<loc>http://x.eg/sitemap-url/eg/sitemap-index.xml</loc>
<lastmod>2015-02-19</lastmod>
</sitemap>
<sitemap xmlns="" id="3">
<loc>http://x.ma/sitemap-url/ma/sitemap-index.xml</loc>
<lastmod>2015-02-19</lastmod>
</sitemap>
<sitemap xmlns="" id="4">
<loc>http://x.om/sitemap-url/om/sitemap-index.xml</loc>
<lastmod>2015-02-19</lastmod>
</sitemap>
<sitemap xmlns="" id="5">
<loc>http://x.qa/sitemap-url/qa/sitemap-index.xml</loc>
<lastmod>2015-02-19</lastmod>
</sitemap>
<sitemap xmlns="" id="6">
<loc>http://x.tn/sitemap-url/tn/sitemap-index.xml</loc>
<lastmod>2015-02-19</lastmod>
</sitemap>
</sitemapindex>
I try to delete this attribute: <sitemap xmlns=""> but it's no possible.
What I'm doing wrong?
This is my code to generate XML:
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
//ROOT ELEMENT:
Element rootElement = doc.createElementNS("http://www.sitemaps.org/schemas/sitemap/0.9", "sitemapindex");
doc.appendChild(rootElement);
SortedSet<Country> countries = locationDao.readAllCountriesSorted();
int i =0;
for(Country c : countries){
Element siteMap = doc.createElement("sitemap");
siteMap.setAttribute("id", String.valueOf(i));
//PUT AN ID
Element loc = doc.createElement("loc");
Element lastMod = doc.createElement("lastmod");
loc.appendChild(doc.createTextNode("http://"+c.getDomain()+"/sitemap-url/"+c.getCode().toLowerCase()+"/sitemap-index.xml"));
lastMod.appendChild(doc.createTextNode(DateUtils.getCurrentDateString()));
rootElement.appendChild(siteMap);
siteMap.appendChild(loc);
siteMap.appendChild(lastMod);
i++;
}
;//always appear.
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
//IDENTEM EL RESULTAT
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
//Si ho volem mostrar en un file:
StreamResult result = new StreamResult(new File("sitemapTest.xml"));
//StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
System.out.println("Document ready....");
I try to delete with removeAttribute method or removeAttNs but seems not working..
Create your sitemap, loc, lastmod elements in the proper namespace ( you currently create it in the null namespace, which in this case is not the default namespace) :
Element siteMap = doc.createElementNS("http://www.sitemaps.org/schemas/sitemap/0.9", "sitemap");
//...
Element loc = doc.createElementNS("http://www.sitemaps.org/schemas/sitemap/0.9", "loc");
Element lastMod = doc.createElementNS("http://www.sitemaps.org/schemas/sitemap/0.9", "lastmod");
It is a while since i did XML with DOM in Java but if i remember correctly you must set the namespace on all elements, so your dom knows which namespace to use. If it does not know this, it will create an empty XML-Namepsace (short: xmlns) which results in the empty attribute you are seeing.
It's not an attribute, it's a namespace declaration. The effect of the namespace declaration is to ensure that your sitemap elements are not in a namespace. It's needed because when you created the sitemap elements, you asked for them to be in no namespace. If you want them in the namespace "http://www.sitemaps.org/schemas/sitemap/0.9", you must create them in that namespace, which you do using createElementNS().
I'm trying to generate a XML from Java.
Something like this:
<?xml version="1.0" encoding="UTF-8"?>
<ElementFile
xmlns="http://www.url.com/bla/bla"
xmlns:common="http://www.url.com/bla/bla/bla">
<Regulation>
<blablaElement>0000-0000</blablaElement>
</Regulation>
</ElementFile>
To do this, I wrote the following code:
ElementFile = document.addElement( "ElementFile" )
.addNamespace("xmlns","http://www.url.com/bla/bla")
.addNamespace("common", "http://www.url.com/bla/bla/bla");
But the generated code is:
<?xml version="1.0" encoding="UTF-8"?>
<ElementFile
xmlns:xmlns="http://www.url.com/bla/bla"
xmlns:common="http://www.url.com/bla/bla/bla">
<Regulation>
<blablaElement>0000-0000</blablaElement>
</Regulation>
</ElementFile>
However, if I write this (without xmlns)
ElementFile = document.addElement( "ElementFile" )
.addNamespace("","http://www.url.com/bla/bla")
.addNamespace("common", "http://www.url.com/bla/bla/bla");
Then, the xml generates the line properly but it adds xmlns=" " by default:
<?xml version="1.0" encoding="UTF-8"?>
<ElementFile
xmlns="http://www.url.com/bla/bla"
xmlns:common="http://www.url.com/bla/bla/bla">
<Regulation xmlns="">
<blablaElement>0000-0000</blablaElement>
</Regulation>
</ElementFile>
I'm quite lost...
[UPDATED QUESTION]
I'm sorry, but I don't understand how to integrated your answer in my code. I am new to this domain.
My complete code is:
XMLWriter writer = new XMLWriter(new FileWriter("xmlFileName"), format);
Document document = DocumentHelper.createDocument();
Element ElementFile = document.addElement( "ElementFile" )
.addNamespace("xmlns","http://www.url.com/bla/bla")
.addNamespace("xmlns:common", "http://www.url.com/bla/bla/bla");
Element Regulation = ElementFile.addElement( "Regulation" );
Element blablaElement = Regulation.addElement( "blablaElement" )
.addText( "0000-0000" );
writer.write(document);
writer.close();
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
dbfac.setNamespaceAware(true);
DocumentBuilder docBuilder;
docBuilder = dbfac.newDocumentBuilder();
DOMImplementation domImpl = docBuilder.getDOMImplementation();
Document doc = domImpl.createDocument("http://www.url.com/bla/bla", "ElementFile ", null);
doc.setXmlVersion("1.0");
doc.setXmlStandalone(true);
Element elementFile = doc.getDocumentElement();
elementFile.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:common","http://www.url.com/bla/bla/bla");
and add elements to this doc
you have a similar question here: How to create attribute (xmlns:xsd) to XML node in Java?
How to read From XML <returnMsg>Successful</returnMsg> value of this tag in java?
How to read the data of the tags in this example.
I am getting The processing instruction target matching "[xX][mM][lL]" is not allowed. Exception is getting
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<doServiceResponse xmlns="http://ocs.ztesoft.com">
<doServiceReturn><?xml version="1.0" encoding="UTF-8"?>
<zsmart>
<Data>
<header>
<returnMsg>Successful</returnMsg>
<ACTION_ID>ModifyBalReturnAllBal</ACTION_ID>
<REQUEST_ID>0032013070900000503</REQUEST_ID>
<returnCode>0</returnCode>
</header>
<body>
<TransactionSN>503</TransactionSN>
</body>
</Data>
</zsmart>
</doServiceReturn></doServiceResponse></soapenv:Body></soapenv:Envelope>
JAVA CODE
dbf = DocumentBuilderFactory.newInstance();
db = dbf.newDocumentBuilder();
is = new InputSource();
is.setCharacterStream(new StringReader(respString));
doc = db.parse(is);
nodes = doc.getElementsByTagName("soapenv:Envelope");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList txnStatus = element.getElementsByTagName("returnCode");
Element line = (Element) txnStatus.item(0);
bean.setTxnStatus(getCharacterDataFromElement(line));
NodeList message = element.getElementsByTagName("returnMsg");
line = (Element) message.item(0);
bean.setMessage(getCharacterDataFromElement(line));
}
Exception
org.xml.sax.SAXParseException: The processing instruction target matching "[xX][mM][lL]" is not allowed.
There are many way to convert XML file to JAVA OBJECT.
SAX and JAXB algorithms are two of them.
JAXB algorithm is more easily to use. i prefer to use JAXB.
HERE is the link that helps you to create Object from XML file.
enjoy it...
http://www.mkyong.com/java/jaxb-hello-world-example/
I need to create an XML document with the following structure:
<?xml version="1.0" ?>
<Cancelacion xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
RfcEmisor="VSI850514HX4"
Fecha="2011-11-23T17:25:06"
xmlns="http://cancelacfd.sat.gob.mx">
<Folios>
<UUID>BD6CA3B1-E565-4985-88A9-694A6DD48448</UUID>
</Folios>
</Cancelacion>
The structure MUST be that way. But I'm not very familiar with the namespace declaration for the XML Elements. I can correctly generate an XML with the following structure:
<?xml version="1.0" ?>
<Cancelacion RfcEmisor="VSI850514HX4"
Fecha="2011-11-23T17:25:06"
xmlns="http://cancelacfd.sat.gob.mx">
<Folios>
<UUID>BD6CA3B1-E565-4985-88A9-694A6DD48448</UUID>
</Folios>
</Cancelacion>
But the problem is that I can't get to include the xmls:xsd and xmlns:xsi correctly. The code for properly generating the previously mentioned code is:
// Crear un document XML vacío
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
dbfac.setNamespaceAware(true);
DocumentBuilder docBuilder;
docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
doc.setXmlVersion("1.0");
doc.setXmlStandalone(true);
Element cancelacion = doc.createElementNS("http://cancelacfd.sat.gob.mx","Cancelacion");
cancelacion.setAttribute("RfcEmisor", rfc);
cancelacion.setAttribute("Fecha", fecha);
doc.appendChild(cancelacion);
Element folios = doc.createElementNS("http://cancelacfd.sat.gob.mx", "Folios");
cancelacion.appendChild(folios);
for (int i=0; i<uuid.length; i++) {
Element u = doc.createElementNS("http://cancelacfd.sat.gob.mx","UUID");
u.setTextContent(uuid[i]);
folios.appendChild(u);
}
You can add additional namespaces by calling setAttributeNS method on the root element
as shown in below example
// get the root element
Element rootElement = xmlDoc.getDocumentElement();
// add additional namespace to the root element
rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
You can then add elements to a given namespace by using the method like below
// append author element to the document element
Element author = xmlDoc.createElement("xsd:element");
Read this article for more details.