I recently just started working with document builder to build a title with my XML. This is the following code I am using right now:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
InputStream inputStream = new FileInputStream(new File("c:\\staff.xml"));
org.w3c.dom.Document doc = documentBuilderFactory.newDocumentBuilder().parse(inputStream);
StringWriter stw = new StringWriter();
Transformer serializer = TransformerFactory.newInstance().newTransformer();
serializer.transform(new DOMSource(doc), new StreamResult(stw));
String xmldata = (stw.toString());
System.out.println(xmldata);
It builds the title fine, but it starts writing the XML file on the same line due to the parse. Can someone show me how I can alter this code to get <company> onto the second line?
Here is my print:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><company>
<comp id="512">
<firstname>Brandon</firstname>
<lastname>Liens</lastname>
<empid>612</empid>
<rqid>51265</rqid>
</comp>
</company>
Staff.XML file:
<company>
<comp id="512">
<firstname>Brandon</firstname>
<lastname>Nyberg</lastname>
<empid>612</empid>
<rqid>51265</rqid>
</comp>
</company>
You can't add a newline after the XML declaration automatically, but if you can deal with removing the XML declaration entirely, you can add this line just after your Transformer serializer = ... line:
serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
Related
I searched on google first and I found many result about how to parse with xpath a xml document. I have parse it but a want to convert a NODELIST in String and I have created a method for it:
private String processResult(Document responseDocument) throws XPathExpressionException, TransformerException {
NodeList soaphead = responseDocument.getElementsByTagName("xmlTagToTrasform");
StringWriter sw = new StringWriter();
Transformer serializer = TransformerFactory.newInstance().newTransformer();
serializer.transform(new DOMSource(soaphead.item(0)), new StreamResult(sw));
String result = sw.toString();
return result;
}
This method works perfectly but the transformer adds an <?xml version="1.0" encoding="UTF-8"?> in the header of the result, and I don't want that. This is the result of the method:
<?xml version="1.0" encoding="UTF-8"?>
<xmlTagToTrasform>
<xmlTagToTrasform2>
.
.
.
.
</xmlTagToTrasform2>
</xmlTagToTrasform>
You can configure the transformer not to output the XML declaration, before you call transform:
serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
XML is a markup language and every xml document has this line on the top to specify the version and the encoding-type. It is madatory to have this.
here's my situation.
I have a string containing XML data:
<tag>
<anotherTag> data </anotherTag>
</tag>
I take that string and I run it through this code to convert it to a Document:
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new InputSource(new StringReader(sXMLString)));
}
catch (Exception e) {
// Parser with specified options can't be built
ceLogger.logError("Unable to build a new XML Document from string provided:\t" + e.getMessage());
return null;
}
The resulting xml is almost perfect. Its missing the data however and looks like this:
<tag>
<anotherTag />
</tag>
How can I copy over the text when creating an XML Document and why is it removing the text in the first place?
Edit:
The actual problem ended up being something along the lines of this:
While parsing through the XML structure with my own function this line is there:
if (curChild.getNodeType()==Node.ELEMENT_NODE)
sResult.append(XMLToString((Element)children.item(i),attribute_mask));
But no such logic exists for TEXT nodes, so they are simply ignored.
Your code is correct. The only guess I can make is that you are outputting your code incorrectly. I've tested your code, and used the following method to output, and the XML was displayed correctly with the text node:
public static void outputXML(Document dom) throws TransformerException
{
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//initialize StreamResult with File object to save to file
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(dom);
transformer.transform(source, result);
String xmlString = result.getWriter().toString();
System.out.println(xmlString);
}
The output was:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<tag> <anotherTag> data </anotherTag>
</tag>
StringWriter writer = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(node), new StreamResult(writer));
out.print("<zhape>"+writer.toString()+"</zhape>");
when i use the code above the the following line also appear in the output.
<?xml version="1.0" encoding="UTF-8"?>
How can i omit this and get just the XML content.
use the OUTPUTKEYS to set the property in the TRANSFORMER. To do what you want you should use the OMIT_XML_DECLARATION output key.
My code write a XML file with the LSSerializer class :
DOMImplementation impl = doc.getImplementation();
DOMImplementationLS implLS = (DOMImplementationLS) impl.getFeature("LS","3.0");
LSSerializer ser = implLS.createLSSerializer();
String str = ser.writeToString(doc);
System.out.println(str);
String file = racine+"/"+p.getNom()+".xml";
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
out.write(str);
out.close();
The XML is well-formed, but when I parse it, I get an error.
Parse code :
File f = new File(racine+"/"+filename);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(f);
XPathFactory xpfactory = XPathFactory.newInstance();
XPath xp = xpfactory.newXPath();
String expression;
expression = "root/nom";
String nom = xp.evaluate(expression, doc);
The error :
[Fatal Error] Terray.xml:1:40: Content is not allowed in prolog.
9 août 2011 19:42:58 controller.MakaluController activatePatient
GRAVE: null
org.xml.sax.SAXParseException: Content is not allowed in prolog.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:249)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:208)
at model.MakaluModel.setPatientActif(MakaluModel.java:147)
at controller.MakaluController.activatePatient(MakaluController.java:59)
at view.ListePatientsPanel.jButtonOKActionPerformed(ListePatientsPanel.java:92)
...
Now, with some research, I found that this error is dure to a "hidden" character at the very beginning of the XML.
In fact, I can fix the bug by creating a XML file manually.
But where is the error in the XML writing ? (When I try to println the string, there is no space before ths
Solution : change the serializer
I run the solution of UTF-16 encoding for a while, but it was not very stable.
So I found a new solution : change the serializer of the XML document, so that the encoding is coherent between the XML header and the file encoding. :
DOMSource domSource = new DOMSource(doc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
String file = racine+"/"+p.getNom()+".xml";
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.transform(domSource, new StreamResult(out));
But where is the error in the XML writing ?
Looks like the error is not in the writing but the parsing. As you have already discovered there is a blank character at the beginning of the file, which causes the error in the parse call in your stach trace:
Document doc = builder.parse(f);
The reason you do not see the space when you print it out may be simply the encoding you are using. Try changing this line:
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
to use 'UTF-16' or 'US-ASCII'
I think that it is probably linked to BOM (Byte Order Mark). See Wikipedia
You can verify with Notepad++ by example : Open your file and check the "Encoding" Menu to see if you're in "UTF8 without BOM" or "UTF8 with BOM".
Using UTF-16 is the way to go,
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(fileName),"UTF-16");
This can read the file with no issues
Try this code:
InputStream is = new FileInputStream(file);
Document doc = builder.parse(is , "UTF-8");
I need to generate an xml file in Java, so I chose to use DOM (until there everything is ok), here is the root tag of what i need to create
<?xml version="1.0" encoding="utf-8"?>
<KeyContainer Version="1.0" xmlns="urn:ietf:params:xml:ns:keyprov:pskc:1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:xml="http://www.w3.org/XML/1998/namespace">
Here is my source code
PrintWriter out = new PrintWriter(path);
Document xmldoc = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
Element e = null;
Node n = null;
xmldoc = impl.createDocument(null, "KeyContainer", null);
/* Noeuds non bouclés */
Element keycontainer = xmldoc.getDocumentElement();
keycontainer.setAttributeNS(null, "Version", "1.0");
keycontainer.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:ds","http://www.w3.org/2000/09/xmldsig#");
keycontainer.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xenc", "http://www.w3.org/2001/04/xmlenc#");
keycontainer.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xml", "http://www.w3.org/XML/1998/namespace");
keycontainer.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "urn:ietf:params:xml:ns:keyprov:pskc:1.0");
/* Non relevant Info*/
DOMSource domSource = new DOMSource(xmldoc);
StreamResult streamResult = new StreamResult(out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING,"utf-8");
serializer.setOutputProperty(OutputKeys.VERSION,"1.0");
serializer.setOutputProperty(OutputKeys.INDENT,"yes");
serializer.setOutputProperty(OutputKeys.STANDALONE,"yes");
serializer.transform(domSource, streamResult);
And here is what I get
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<KeyContainer xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Version="1.0">
Problem is the xmlns property is empty, and xmlns:xml is missing, what can I do to get all information ?
Thanks a lot stackoverflow
(PS : Got NAMESPACE_ERR if anything else than "http://www.w3.org/2000/xmlns/" in NamespaceURI field)
Two things are required to get rid of xmlns=""
Create the Document with the desired namespace URI as such:
xmldoc = impl.createDocument("urn:ietf:params:xml:ns:keyprov:pskc:1.0", "KeyContainer", null);
Remove the following line as it is now unnecessary:
keycontainer.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "urn:ietf:params:xml:ns:keyprov:pskc:1.0");
Regarding the xmlns:xml attribute, the API is silently dropping it. See line 173 of NamespaceMappings. A bit of research turns up that the behavior of declaring that particular namespace is undefined and is not recommended.
To make DOM namespace aware, do not forget to enable it in the documentbuilderfactory using the setNamespaceAware method.