How to create XML file with specific structure in Java
You can use the JDOM library in Java.
Define your tags as Element objects, document your elements with Document Class, and build your xml file with SAXBuilder. Try this example:
//Root Element
Element root=new Element("CONFIGURATION");
Document doc=new Document();
//Element 1
Element child1=new Element("BROWSER");
//Element 1 Content
child1.addContent("chrome");
//Element 2
Element child2=new Element("BASE");
//Element 2 Content
child2.addContent("http:fut");
//Element 3
Element child3=new Element("EMPLOYEE");
//Element 3 --> In this case this element has another element with Content
child3.addContent(new Element("EMP_NAME").addContent("Anhorn, Irene"));
//Add it in the root Element
root.addContent(child1);
root.addContent(child2);
root.addContent(child3);
//Define root element like root
doc.setRootElement(root);
//Create the XML
XMLOutputter outter=new XMLOutputter();
outter.setFormat(Format.getPrettyFormat());
outter.output(doc, new FileWriter(new File("myxml.xml")));
Create XML file using java
You can use a DOM XML parser to create an XML file using Java. A good example can be found on this site:
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 firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode("yong"));
staff.appendChild(firstname);
//lastname elements
Element lastname = doc.createElement("lastname");
lastname.appendChild(doc.createTextNode("mook kim"));
staff.appendChild(lastname);
//nickname elements
Element nickname = doc.createElement("nickname");
nickname.appendChild(doc.createTextNode("mkyong"));
staff.appendChild(nickname);
//salary elements
Element salary = doc.createElement("salary");
salary.appendChild(doc.createTextNode("100000"));
staff.appendChild(salary);
//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:\\testing.xml"));
transformer.transform(source, result);
System.out.println("Done");
}catch(ParserConfigurationException pce){
pce.printStackTrace();
}catch(TransformerException tfe){
tfe.printStackTrace();
}
What is the best way to create XML files in Java?
If you just want to write an XML document having exact control over the creating of elements, attributes and other document components, you may use the XMLStreamWriter from the StAX API.
Java creating a new xml file and appending it
I simulated your code here and did realized the you are not creating a valid root element in XML file, that's why you getting the exception.
See my results that I am getting running the write method:
public static void main(String... x) {
Sentence s = new Sentence();
Main m = new Main();
List<Sentence> list = new ArrayList<Sentence>();
list.add(s);
m.write(list);
}
Sentence class:
public class Sentence {
public String[] getWordList() {
return new String[] { "w4", "w5", "w6" }; // previous: w1,w2,w3
}
}
file.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<text>
<sentence>
<word>w1</word>
<word>w2</word>
<word>w3</word>
</sentence>
<sentence>
<word>w4</word>
<word>w5</word>
<word>w6</word>
</sentence>
<sentence>
<word>w4</word>
<word>w5</word>
<word>w6</word>
</sentence>
</text>
Solution:
Just replace your code with the following:
// text element
Element rootElement = null;
if (!fileExist) {
rootElement = doc.createElement("text");
doc.appendChild(rootElement);
} else {
rootElement = doc.getDocumentElement(); // get the root [text] element
}
How to generate xml file with an existing dtd for sample of data using Java
A couple of observations/suggestions:
1) What do you need the XML output to look like?
Assume you have a Points
class like this:
import java.util.Map;
import java.util.HashMap;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "root")
public class Points {
public Points() {};
public Points(Map<Position, Double> listOfPoints) {
this.listOfPoints = listOfPoints;
}
@XmlElement(name = "list_of_points")
private Map<Position, Double> listOfPoints;
public Map<Position, Double> getListOfPoints() {
if (listOfPoints == null) {
listOfPoints = new HashMap();
}
return this.listOfPoints;
}
}
and a Position
class like this:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "position")
public class Position {
@XmlElement(required = true)
protected String x;
@XmlElement(required = true)
protected String y;
public String getX() {
return x;
}
public void setX(String value) {
this.x = value;
}
public String getY() {
return y;
}
public void setY(String value) {
this.y = value;
}
}
Without using a DTD, you can generate XML like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<listOfPoints>
<entry>
<key>
<x>pos1 x</x>
<y>pos1 y</y>
</key>
<value>123.456</value>
</entry>
<entry>
<key>
<x>pos2 x</x>
<y>pos2 y</y>
</key>
<value>456.789</value>
</entry>
</listOfPoints>
</root>
The code to do that is:
JAXBContext jc = JAXBContext.newInstance(Points.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
File xml = new File("/path/to/points.xml");
marshaller.marshal(points, xml);
Is that sufficient for your needs?
2) Using your DTD
I'm not sure how your DTD is going to help you, because it implies a set of unrelated and overlapping Java objects from which the final XML will be created.
To see what I mean, try it for yourself.
Using the xjc
tool (see here), you can generate Java objects from your DTD:
/path/to/jdk/bin/xjc -d output -p org.ajames.jaxbdemo.points -dtd my_schema.dtd
Using these Java classes, you can populate your data structure (your listOfPoints
). And then you can create the XML output from that (as shown above, using the JAXB marshaller).
But your DTD will create some not-very-useful objects...
So, that comes back to the initial question: What do you want your XML to look like?
3) Use an XSD?
If you manually create a sample of your required XML, you can then generate an XSD from it. There are various online tools to help with that. Then you can use the xjc
command again (but this time for an XSD not a DTD). And then you can use the resulting Java objects to get the exact XML you need.
Create XML document using nodeList
You should do it like this:
- you create a new
org.w3c.dom.Document newXmlDoc
where you store the nodes in yourNodeList
, - you create a new root element, and append it to
newXmlDoc
- then, for each node
n
in yourNodeList
, you importn
innewXmlDoc
, and then you appendn
as a child ofroot
Here is the code:
public static void main(String[] args) {
String exp = "/configs/markets/market";
String path = "src/a/testConfig.xml";
try {
Document xmlDocument = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(path);
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression xPathExpression = xPath.compile(exp);
NodeList nodes = (NodeList) xPathExpression.
evaluate(xmlDocument, XPathConstants.NODESET);
Document newXmlDocument = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
Element root = newXmlDocument.createElement("root");
newXmlDocument.appendChild(root);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Node copyNode = newXmlDocument.importNode(node, true);
root.appendChild(copyNode);
}
printTree(newXmlDocument);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void printXmlDocument(Document document) {
DOMImplementationLS domImplementationLS =
(DOMImplementationLS) document.getImplementation();
LSSerializer lsSerializer =
domImplementationLS.createLSSerializer();
String string = lsSerializer.writeToString(document);
System.out.println(string);
}
The output is:
<?xml version="1.0" encoding="UTF-16"?>
<root><market>
<name>Real</name>
</market><market>
<name>play</name>
</market></root>
Some notes:
- I've changed
exp
to/configs/markets/market
, because I suspect you want to copy themarket
elements, rather than the singlemarkets
element - for the
printXmlDocument
, I've used the interesting code in this answer
I hope this helps.
If you don't want to create a new root element, then you may use your original XPath expression, which returns a NodeList
consisting of a single node (keep in mind that your XML must have a single root element) that you can directly add to your new XML document.
See following code, where I commented lines from the code above:
public static void main(String[] args) {
//String exp = "/configs/markets/market/";
String exp = "/configs/markets";
String path = "src/a/testConfig.xml";
try {
Document xmlDocument = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(path);
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression xPathExpression = xPath.compile(exp);
NodeList nodes = (NodeList) xPathExpression.
evaluate(xmlDocument,XPathConstants.NODESET);
Document newXmlDocument = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
//Element root = newXmlDocument.createElement("root");
//newXmlDocument.appendChild(root);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Node copyNode = newXmlDocument.importNode(node, true);
newXmlDocument.appendChild(copyNode);
//root.appendChild(copyNode);
}
printXmlDocument(newXmlDocument);
} catch (Exception ex) {
ex.printStackTrace();
}
}
This will give you the following output:
<?xml version="1.0" encoding="UTF-16"?>
<markets>
<market>
<name>Real</name>
</market>
<market>
<name>play</name>
</market>
</markets>
Generating xml file with & using java
I need to write
<name> Dolce & Gabanna </name>
in an xml file using java.
No, you don't. Not unless you're trying to create an invalid file. Whatever code you're using is doing exactly the right thing - any XML parser reading the file will then unescape the &
to &
where appropriate.
From the XML 1.0 specification, section 2.4:
The ampersand character (
&
) and the left angle bracket (<
) must not appear in their literal form, except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section. If they are needed elsewhere, they must be escaped using either numeric character references or the strings "&
" and "<
" respectively.
How to create XML file without external libraries in Java 9?
You can use these libraries in Java 9, but you need to require the module that contains them. Ensure that your module-info.java
has a requirement for the java.xml
module:
module myModule {
requires java.xml;
}
As you require more functionality from the JAXB modules, you will need to add more requires
statements in your module-info.java
file. For example, your module-info.java
file may look more like the following when you are done:
module myModule {
java.xml
java.xml.bind
java.xml.ws
java.xml.ws.annotation
}
For more information, see How to resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
in Java 9.
How to read and write XML files?
Here is a quick DOM example that shows how to read and write a simple xml file with its dtd:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE roles SYSTEM "roles.dtd">
<roles>
<role1>User</role1>
<role2>Author</role2>
<role3>Admin</role3>
<role4/>
</roles>
and the dtd:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT roles (role1,role2,role3,role4)>
<!ELEMENT role1 (#PCDATA)>
<!ELEMENT role2 (#PCDATA)>
<!ELEMENT role3 (#PCDATA)>
<!ELEMENT role4 (#PCDATA)>
First import these:
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.w3c.dom.*;
Here are a few variables you will need:
private String role1 = null;
private String role2 = null;
private String role3 = null;
private String role4 = null;
private ArrayList<String> rolev;
Here is a reader (String xml is the name of your xml file):
public boolean readXML(String xml) {
rolev = new ArrayList<String>();
Document dom;
// Make an instance of the DocumentBuilderFactory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
// use the factory to take an instance of the document builder
DocumentBuilder db = dbf.newDocumentBuilder();
// parse using the builder to get the DOM mapping of the
// XML file
dom = db.parse(xml);
Element doc = dom.getDocumentElement();
role1 = getTextValue(role1, doc, "role1");
if (role1 != null) {
if (!role1.isEmpty())
rolev.add(role1);
}
role2 = getTextValue(role2, doc, "role2");
if (role2 != null) {
if (!role2.isEmpty())
rolev.add(role2);
}
role3 = getTextValue(role3, doc, "role3");
if (role3 != null) {
if (!role3.isEmpty())
rolev.add(role3);
}
role4 = getTextValue(role4, doc, "role4");
if ( role4 != null) {
if (!role4.isEmpty())
rolev.add(role4);
}
return true;
} catch (ParserConfigurationException pce) {
System.out.println(pce.getMessage());
} catch (SAXException se) {
System.out.println(se.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
return false;
}
And here a writer:
public void saveToXML(String xml) {
Document dom;
Element e = null;
// instance of a DocumentBuilderFactory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
// use factory to get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
// create instance of DOM
dom = db.newDocument();
// create the root element
Element rootEle = dom.createElement("roles");
// create data elements and place them under root
e = dom.createElement("role1");
e.appendChild(dom.createTextNode(role1));
rootEle.appendChild(e);
e = dom.createElement("role2");
e.appendChild(dom.createTextNode(role2));
rootEle.appendChild(e);
e = dom.createElement("role3");
e.appendChild(dom.createTextNode(role3));
rootEle.appendChild(e);
e = dom.createElement("role4");
e.appendChild(dom.createTextNode(role4));
rootEle.appendChild(e);
dom.appendChild(rootEle);
try {
Transformer tr = TransformerFactory.newInstance().newTransformer();
tr.setOutputProperty(OutputKeys.INDENT, "yes");
tr.setOutputProperty(OutputKeys.METHOD, "xml");
tr.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
tr.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "roles.dtd");
tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
// send DOM to file
tr.transform(new DOMSource(dom),
new StreamResult(new FileOutputStream(xml)));
} catch (TransformerException te) {
System.out.println(te.getMessage());
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
} catch (ParserConfigurationException pce) {
System.out.println("UsersXML: Error trying to instantiate DocumentBuilder " + pce);
}
}
getTextValue is here:
private String getTextValue(String def, Element doc, String tag) {
String value = def;
NodeList nl;
nl = doc.getElementsByTagName(tag);
if (nl.getLength() > 0 && nl.item(0).hasChildNodes()) {
value = nl.item(0).getFirstChild().getNodeValue();
}
return value;
}
Add a few accessors and mutators and you are done!
Related Topics
Why Doesn't Java.Lang.Number Implement Comparable
Looking for Java Spell Checker Library
How to Convert a String to a Secretkey
Converting to Upper and Lower Case in Java
@Preupdate and @Prepersist in Hibernate/JPA (Using Session)
How to Redirect Processbuilder's Output to a String
Is Asynchronous Jdbc Call Possible
Jdbc Driver Throws "Resultset Closed" Exception on Empty Resultset
How to Loop User Input Until an Integer Is Inputted
Should I Use a Separate Scriptengine and Compiledscript Instances Per Each Thread