Create a Complex XMl file using Java - java

I need to create a XML file using java, I got the file as I like but i am missing relation tag before every end tag, How Can I get that
Expected File:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<FlyBoy>
<learJet>CL-215</learJet>
<rank>2</rank>
<FlyBoy>
<viper>Mark II</viper>
<rank>1</rank>
<FlyBoy>
<viper>Mark II4455</viper>
<rank>2</rank>
<FlyBoy>
<viper>Mark II56666</viper>
<rank>3</rank>
<relation name="Date" table="Sam"/>
</FlyBoy>
<relation name="Date" table="Mark"/>
</FlyBoy>
<relation name="Date" table="sechma"/>
</FlyBoy>
<relation name="Date" table="John"/>
</FlyBoy>
Output I got:
<FlyBoy><learJet>CL-215</learJet><rank>2</rank><FlyBoy><viper>Mark II</viper><rank>1</rank><FlyBoy><viper>Mark II4455</viper><rank>2</rank><FlyBoy><viper>Mark II56666</viper><rank>3</rank></FlyBoy></FlyBoy></FlyBoy></FlyBoy>
Code:
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 org.w3c.dom.Document;
import org.w3c.dom.Element;
public class XmlGenerator {
/**
* Render flyboy
*
*/
private Element renderFlyBoy(Element parent, String viper, String rank) {
Element flyBoyEl = document.createElement("FlyBoy");
parent.appendChild(flyBoyEl);
Element viperEl = document.createElement("viper");
viperEl.setTextContent(viper);
flyBoyEl.appendChild(viperEl);
Element rankEl = document.createElement("rank");
rankEl.setTextContent(rank);
flyBoyEl.appendChild(rankEl);
return flyBoyEl;
}
// Test
public static void main(String[] args) {
try {
Document document = null;
Element root = null;
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
document = documentBuilderFactory.newDocumentBuilder().newDocument();
root = document.createElement("FlyBoy");
document.appendChild(root);
Element learJet = document.createElement("learJet");
learJet.setTextContent("CL-215");
root.appendChild(learJet);
Element rank = document.createElement("rank");
rank.setTextContent("2");
root.appendChild(rank);
Element flyBoy1 = renderFlyBoy(root, "Mark II", "1");
Element flyBoy2 = renderFlyBoy(flyBoy1, "Mark II4455", "2");
Element flyBoy3 = renderFlyBoy(flyBoy2, "Mark II56666", "3");
Element relation_schema= doc.createElement("relation");
flyBoy1.appendChild(relation_schema);
Attr join2 = doc.createAttribute("name");
join2.setValue("Date");
relation_schema.setAttributeNode(join2);
Attr type = doc.createAttribute("table");
type.setValue("xxxxxx");
relation_schema.setAttributeNode(type);
DOMSource domSource = new DOMSource(document);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
StreamResult result = new StreamResult(new File("my.xml"));
transformer.transform(domSource, result);
} catch (ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException e) {
e.printStackTrace();
}
System.out.println("done...");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Inside the renderFlyBoy method you need to create the relation in the same way you created others. Then relation will be added inside FlyBoy
Element rankEl = document.createElement("relation");
// code to add attributes
flyBoyEl.appendChild(rankEl);

Related

XMLStreamWriter write tag containing colon

When I use colon in the tag name like in the example below, it ends up in error (there is no problem with tags without the colon).
package test;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class SomeClass{
public StringWriter test() throws XMLStreamException, TransformerConfigurationException, TransformerException {
StringWriter stringOut = new StringWriter();
XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(stringOut);
xmlWriter.writeStartDocument("UTF-8", "1.0");
xmlWriter.writeStartElement("SomeWordHere");
{
xmlWriter.writeStartElement("SomeName:enable");//<--- notice the colon
xmlWriter.writeCharacters("true");
xmlWriter.writeEndElement();
}
xmlWriter.writeEndElement();
xmlWriter.writeEndDocument();
xmlWriter.flush();
xmlWriter.close();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
StringWriter formattedStringWriter = new StringWriter();
transformer.transform(new StreamSource(new StringReader(stringOut.toString())), new StreamResult(formattedStringWriter));
return formattedStringWriter;
}
}
How to write the tag that would still conain the colon and would not end up in error?
I am trying to emulate the XML output (Collada DAE) produced by LEGO Stud.io software, there are sections like the one below containing tag names with colons.
<library_materials>
<material id="material_id_7" name="SOLID-BLUE">
<instance_effect url="#effect_id_7-fx" />
<extra>
<technique profile="eyesight">
<ScratchBump:enable> true </ScratchBump:enable>
<MinScratchStrength:value> 0 </MinScratchStrength:value>
<MaxScratchStrength:value> 0.2 </MaxScratchStrength:value>
<BigScratch:enable> true </BigScratch:enable>
<SmallScratch:enable> true </SmallScratch:enable>
</technique>
</extra>
</material>
</library_materials>
Colon is used for namespaces and per "Namespaces in XML" specification, it cannot be used in entity names.
The specification states:
[Definition: A document is namespace-well-formed if it conforms to
this specification. ]
It follows that in a namespace-well-formed document:
All element and attribute names contain either zero or one colon;
No entity names, processing instruction targets, or notation names contain any colons.
You can use a trick that is to declare "SomeName" as a namespace as it is suggested in this question: xml schema validation error "prefix is not bound".
On the other hand, "Extensible Markup Language" Specification state that:
Note:
The Namespaces in XML Recommendation [XML Names] assigns a meaning to
names containing colon characters. Therefore, authors should not use
the colon in XML names except for namespace purposes, but XML
processors must accept the colon as a name character.
If you change the parser you can get what you want:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class CreateXmlFileDemo {
public static void main(String[] args) {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.newDocument();
Element rootElement = doc.createElement("SomeName:enable");
doc.appendChild(rootElement);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult consoleResult = new StreamResult(System.out);
transformer.transform(source, consoleResult);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Reference: https://www.w3.org/TR/REC-xml-names/

What is the cause of the "Premature end of file, org. xml. sax. SAXParseException" exception?

I am using sax to create an xml file, but when I run the program, the following error occurs:
[Fatal Error] :-1:-1: Premature end of file.
org.xml.sax.SAXParseException; Premature end of file.
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:205)
I checked the files written, but I didn't see any problems.The following is my code and the xml file of the operation.
1. Code
The main logic of the following code is: create an XML node, and then append this node to the old file.
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class XmlWriterByDom {
private static final XMLConfigUtils xmlConfig = XMLConfigUtils.getInstance();
public void xmlInsert(Map<String, String> xmlNode, String xmlPath) {
Document doc = xmlConfig.getDocument(xmlPath);
Text nodeValue;
Element root = doc.getDocumentElement();
Element food = doc.createElement(XmlTag.FOOD);
Element name = doc.createElement(XmlTag.NAME);
Element price = doc.createElement(XmlTag.PRICE);
Element desc = doc.createElement(XmlTag.DESC);
nodeValue = doc.createTextNode(xmlNode.get(XmlTag.FOOD));
name.appendChild(nodeValue);
food.appendChild(name);
nodeValue = doc.createTextNode(xmlNode.get(XmlTag.PRICE));
price.appendChild(nodeValue);
food.appendChild(price);
nodeValue = doc.createTextNode(xmlNode.get(XmlTag.DESC));
desc.appendChild(nodeValue);
food.appendChild(desc);
root.appendChild(food);
try {
xmlPath = Objects.requireNonNull( this.getClass().getClassLoader().getResource(xmlPath)).getPath();
TransformerFactory transformer = TransformerFactory.newInstance();
Transformer trans = transformer.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(xmlPath).toURI().getPath());
trans.transform(source, result);
} catch (TransformerException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Map<String, String> xmlNode = new HashMap<>(3);
xmlNode.put("name", "tomato");
xmlNode.put("price", "$10");
xmlNode.put("description", "dishes");
new XmlWriterByDom().xmlInsert(xmlNode, "xml/henan-dishes.xml");
}
}
2. XML
<?xml version="1.0" encoding="UTF-8" ?>
<menu>
<food>
<name>1</name>
<price>18$</price>
<description>2</description>
</food>
<food>
<name>1</name>
<price>59$</price>
<description>2</description>
</food>
</menu>
When I try to delete the compiled folder with the target name and re-execute, the result is correct. May be really a problem with the file system!
Project structure

XML Append - Java

I have the below code that appends to an xml file. The problem is that it includes the xml configuration line each time it appends along with the main element. It works fine for the first record added to the file because there is not previous existing elements. How would I modify this code to exclude those lines for an existing file with existing elements?
import java.io.FileWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
public class WriteXMLFile {
public static void main() throws ParserConfigurationException,SAXException,Exception{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();//
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();//
Document doc = docBuilder.newDocument();// this is difrent
Element rootElement = doc.createElement("Contacts");//
doc.appendChild(rootElement); // this is difrent
Element Contact1 = doc.createElement("Contact1");
rootElement.appendChild(Contact1);
Contact1.setAttribute("id","1");
Element firstname = doc.createElement("Name");
firstname.appendChild(doc.createTextNode(EmailFrame.name.getText()));
Contact1.appendChild(firstname);
//Email Element
Element email = doc.createElement("Email");
email.appendChild(doc.createTextNode(EmailFrame.email.getText()));
Contact1.appendChild(email);
// phone element
Element phone= doc.createElement("Phone");
phone.appendChild(doc.createTextNode(EmailFrame.phone.getText()));
Contact1.appendChild(phone);
//id element
Element id = doc.createElement("ID");
id.appendChild(doc.createTextNode(EmailFrame.id.getText()));
Contact1.appendChild(id);
try{
// 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("C:/Users/steve/Desktop/xmlemail/Email.xml",true));
transformer.transform(source, result);
System.out.println("File saved!");
}
catch (TransformerException tfe) {
tfe.printStackTrace();
}
}}
If you are looking for "overriding" the file then you shall use
StreamResult result = new StreamResult(new FileWriter("D:/tmp/Email.xml")); as boolean parameter just appends to the document.
If you indeed want to append but don't want <?xml version="1.0" encoding="UTF-8" standalone="no"?> then you will have to "read" the file, get the root node and then add elements to the root node.
Remember if you just keep on adding nodes to the document and not to the root element, then even without <?xml version="1.0" encoding="UTF-8" standalone="no"?>, your xml will be invalid, as it will contain multiple root elements "contacts".
Something like:
Document doc = null;
Node rootElement = null;
if (f.exists()) {
doc = docBuilder.parse("C:/Users/steve/Desktop/xmlemail/Email.xml");
rootElement = doc.getFirstChild();//
} else {
doc = docBuilder.newDocument();// this is difrent
rootElement = doc.createElement("Contacts");//
doc.appendChild(rootElement); // this is difrent
}
And then save the document to file without appending.

File name truncation in java.io.File(String) if the file name contains '#'

I am trying to create a new file using java.io.File(String). If the filepath string contains '#' symbol means, created file's name gets truncated. Please anyone explain me why it's happening and how to create the filename with '#' from java.
My code.
new File("d:\\file#test.xml");
Expected output:
file#test.xml
Real output:
file
Note: I need to create the file in both windows and Unix file system.
Normally both windows and Unix systems are allowed to create a filename with #.
Edited:
Thanks to all your reply. yes, problem is not in java.io.File(String). Actually i am getting this problem when i am trying to create the xml file using xml transformer.
please find the full code below.
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
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 org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
public class XMLWriterDOM {
public static void main(String[] args) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
try {
dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.newDocument();
//add elements to Document
Element rootElement =
doc.createElementNS("http://www.journaldev.com/employee", "Employees");
//append root element to document
doc.appendChild(rootElement);
//append first child element to root element
rootElement.appendChild(getEmployee(doc, "1", "Pankaj", "29", "Java Developer", "Male"));
//for output to file,
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
//for pretty print
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult file = new StreamResult(new File("d:\\\\emps#1.xml"));
//write data
transformer.transform(source, file);
System.out.println("DONE");
} catch (Exception e) {
e.printStackTrace();
}
}
private static Node getEmployee(Document doc, String id, String name, String age, String role,
String gender) {
Element employee = doc.createElement("Employee");
//set id attribute
employee.setAttribute("id", id);
//create name element
employee.appendChild(getEmployeeElements(doc, employee, "name", name));
//create age element
employee.appendChild(getEmployeeElements(doc, employee, "age", age));
//create role element
employee.appendChild(getEmployeeElements(doc, employee, "role", role));
//create gender element
employee.appendChild(getEmployeeElements(doc, employee, "gender", gender));
return employee;
}
//utility method to create text node
private static Node getEmployeeElements(Document doc, Element element, String name, String value) {
Element node = doc.createElement(name);
node.appendChild(doc.createTextNode(value));
return node;
}
}
Please suggest me to solve this issue.
I can't reproduce your problem under Mac OS X.
import java.nio.file.Path;
import java.nio.file.Paths;
public class Main {
public static void main(String[] args) {
String temp = System.getProperty("java.io.tmpdir");
Path path = Paths.get(temp, "foo#bar.txt");
System.out.println(path.toAbsolutePath());
}
}
Output:
/var/folders/qm/0t0z2hfx6lb53gf7d8h2srzm0000gp/T/foo#bar.txt
What is the code that makes the output?

inserting xml:space='preserve' in the DOM

Java, Xerces 2.9.1
insertHere.setAttributeNS(XMLConstants.XML_NS_URI, "xml:space", "preserve");
and
insertHere.setAttributeNS(XMLConstants.XML_NS_URI, "space", "preserve")
both end up with an attribute of just space='preserve', no XML prefix.
insertHere.setAttribute( "xml:space", "preserve")
works, but it seems somehow wrong. Am I missing anything?
EDIT
I checked.
I read a template document in with setNamespaceAware turned on.
I then use the following to make a copy of it, and then I start inserting new elements.
public static Document copyDocument(Document input) {
DocumentType oldDocType = input.getDoctype();
DocumentType newDocType = null;
Document newDoc;
String oldNamespaceUri = input.getDocumentElement().getNamespaceURI();
if (oldDocType != null) {
// cloning doctypes is 'implementation dependent'
String oldDocTypeName = oldDocType.getName();
newDocType = input.getImplementation().createDocumentType(oldDocTypeName,
oldDocType.getPublicId(),
oldDocType.getSystemId());
newDoc = input.getImplementation().createDocument(oldNamespaceUri, oldDocTypeName,
newDocType);
} else {
newDoc = input.getImplementation().createDocument(oldNamespaceUri,
input.getDocumentElement().getNodeName(),
null);
}
Element newDocElement = (Element)newDoc.importNode(input.getDocumentElement(), true);
newDoc.replaceChild(newDocElement, newDoc.getDocumentElement());
return newDoc;
}
When I run the following code:
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Demo {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Element rootElement = document.createElement("root");
document.appendChild(rootElement);
rootElement.setAttributeNS(XMLConstants.XML_NS_URI, "space", "preserve");
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(new DOMSource(document), new StreamResult(System.out));
}
}
I get the following output:
<root xml:space="preserve"/>
How are you building your document?

Categories