How to add namespace prefix in Java DOM XML builder - java

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.

Related

Java - Writing to XML file indents everything except the first element

Using JAVA, I am trying, after having opened a .xml file, to append the creation of a new node using a SWING Application. Every new node gets entered correctly EXCEPT the first element which always get stuck at the far left of the file, with no identation.
schedule.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schedule>
<Lesson>
<Title>Artificial Intelligence</Title>
<Lecture>
<Day>Thursday</Day>
</Lecture>
<Professor>John Doe</Professor>
</Lesson>
<Lesson>
<Title>Constraint Satisfaction Problems</Title>
<Lecture>
<Day>Monday</Day>
</Lecture>
</Lesson>
</Schedule>
My attempt to write to the file :
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("schedule.xml");
Element root = document.getDocumentElement();
Element newLesson = document.createElement("Lesson");
Element newTitle = document.createElement("Title");
newTitle.appendChild(document.createTextNode("myLesson"));
newLesson.appendChild(newTitle);
Element newLecture = document.createElement("Lecture");
newLesson.appendChild(newLecture);
Element newDay = document.createElement("Day");
newDay.appendChild(document.createTextNode("myDay"));
newLecture.appendChild(newDay);
Element newProfessor = document.createElement("Professor");
newProfessor.appendChild(document.createTextNode("myProfessor"));
newLesson.appendChild(newProfessor);
root.appendChild(newLesson);
DOMSource source = new DOMSource(document);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
StreamResult result = new StreamResult("schedule.xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "8");
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schedule>
<Lesson>
<Title>Artificial Intelligence</Title>
<Lecture>
<Day>Thursday</Day>
</Lecture>
<Professor>John Doe</Professor>
</Lesson>
<Lesson>
<Title>Constraint Satisfaction Problems</Title>
<Lecture>
<Day>Monday</Day>
</Lecture>
</Lesson>
<Lesson>
<Title>myLesson</Title>
<Lecture>
<Day>myDay</Day>
</Lecture>
<Professor>myProfessor</Professor>
</Lesson>
</Schedule>
Solution: used a function for space trimming from here
Function:
private static void removeEmptyText(Node node){
Node child = node.getFirstChild();
while(child!=null){
Node sibling = child.getNextSibling();
if(child.getNodeType()==Node.TEXT_NODE){
if(child.getTextContent().trim().isEmpty())
node.removeChild(child);
}else
removeEmptyText(child);
child = sibling;
}
}

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 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()

Output format of XML empty element in Java

I wrote code below to get XML output.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Element element = document.createElement("Test");
Text text = document.createTextNode("");
element.appendChild(text);
document.appendChild(element);
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
What I got is
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Test/>
What I want to get is
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Test></Test>
How can I do this?
Many thanks.
There is no clean way to do this..
If you feel comfortable to use duct-tape solutions, you could let your transformer output html instead of xml:
transformer.setOutputProperty(javax.xml.transform.OutputKeys.METHOD, "html");
But again, I have to point out that this is not a clean solution, but it did the trick for me as I was stuck with a similar problem

Java - Add to DOM XML File

I have the following XML, I would like to add another "product" to the xml.
<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<product>
<name>Computer</name>
<code>PC1003</code>
<description>Basic Computer</description>
<price>399.99</price>
</product>
<product>
<name>Monitor</name>
<code>MN1003</code>
<description>LCD Monitor</description>
<price>99.99</price>
</product>
<product>
<name>Printer</name>
<code>PR1003x</code>
<description>Inkjet Printer</description>
<price>54.23</price>
</product>
</products>
This is the code I have so far:
// Variables
File file = new File("db_products.xml"); // set xml to parse
// Create builders
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file); // load xml file
doc.getDocumentElement().normalize();
doc.createElement("product");
I don't really care where the new "product" section is added. I just can't seem to grasp what is the difference between a node and an element. I'm assuming the correct way to add a new "product" section would be to add a child to "products" and then add children (name,code,etc.) to "product".
Any help on how to easily do this, or a link to a simple tutorial would be appreciated.
What you need to do is retrieve the products element first and then call the appendChild on that element. Something like this:
Element productElement = doc.createElement("product");
productElement.setAttribute("name", "value");
//Other name value pairs...
//Append the products element to the right spot.
Element productsElement = (Element) doc.getElementByTagName("products").item(0);
productsElement.appendChild(productElement);
//Convert doc to xml string
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 xmlAsString = writer.toString();

Categories