I'm using Java's built in XML transformer to take a DOM document and print out the resulting XML. The problem is that it isn't indenting the text at all despite having set the parameter "indent" explicitly.
sample code
public class TestXML {
public static void main(String args[]) throws Exception {
ByteArrayOutputStream s;
Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Transformer t = TransformerFactory.newInstance().newTransformer();
Element a,b;
a = d.createElement("a");
b = d.createElement("b");
a.appendChild(b);
d.appendChild(a);
t.setParameter(OutputKeys.INDENT, "yes");
s = new ByteArrayOutputStream();
t.transform(new DOMSource(d),new StreamResult(s));
System.out.println(new String(s.toByteArray()));
}
}
result
<?xml version="1.0" encoding="UTF-8" standalone="no"?><a><b/></a>
desired result
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<a>
<b/>
</a>
Thoughts?
You need to enable 'INDENT' and set the indent amount for the transformer:
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
Update:
Reference : How to strip whitespace-only text nodes from a DOM before serialization?
(Many thanks to all members especially #marc-novakowski, #james-murty and #saad):
Neither of the suggested solutions worked for me. So I kept on searching for an alternative solution, which ended up being a mixture of the two before mentioned and a third step.
set the indent-number into the transformerfactory
enable the indent in the transformer
wrap the otuputstream with a writer (or bufferedwriter)
//(1)
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));
//(2)
Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.INDENT, "yes");
//(3)
t.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "utf-8"));
You must do (3) to workaround a "buggy" behavior of the
xml handling code.
Source: johnnymac75 # http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446
(If I have cited my source incorrectly please let me know)
The following code is working for me with Java 7. I set the indent (yes) and indent-amount (2) on the transformer (not the transformer factory) to get it working.
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(source, result);
#mabac's solution to set the attribute didn't work for me, but #lapo's comment proved helpful.
import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory
transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2");
If you want the indentation, you have to specify it to the TransformerFactory.
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));
Transformer t = tf.newTransformer();
For me adding DOCTYPE_PUBLIC worked:
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "10");
I used the Xerces (Apache) library instead of messing with Transformer. Once you add the library add the code below.
OutputFormat format = new OutputFormat(document);
format.setLineWidth(65);
format.setIndenting(true);
format.setIndent(2);
Writer outxml = new FileWriter(new File("out.xml"));
XMLSerializer serializer = new XMLSerializer(outxml, format);
serializer.serialize(document);
Related
I'm trying to print an XML file colored on console using java, but I have never done this before, and I have no idea how to do that.
This code prints an XML file on console.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder1;
builder1 = factory.newDocumentBuilder();
Document document;
document = builder1.parse(new File(pathFilename));
TransformerFactory tFactory = TransformerFactory.newInstance();
tFactory.setAttribute("indent-number", new Integer(2));
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(document);
StreamResult result2 = new StreamResult(System.out);
transformer.transform(source, result2);
I would like to print it on console like an editor, for example Notepad++.
Any suggests how to do it?
An example of output on console:
<ControllerMode dataItemId="mode" sequence="286201" timestamp="2019-06-27T11:23:02.641182Z">AUTOMATIC</ControllerMode>
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.
I already looked through the postings on stackoverflow but it seems that nothing helps.
Here is what have:
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute("indent-number", 2);
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(xmlDoc);
StreamResult result = new StreamResult(new File("C:\\testing.xml"));
transformer.transform(source, result);
and this is what I get as output:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Satellite SatelliteName="" XmlFileVersion="">
<test0>
<test1>
<test2>
<test3>
<test4>
<test5>
<test6>
<test7>
<test8>
<test9/>
</test8>
</test7>
</test6>
</test5>
</test4>
</test3>
</test2>
</test1>
</test0>
</Satellite>
No tabs or no spaces.
I set the indent-number because of a possible bug of java and I activated OutputKeys.INDENT.
Any other ideas?
Edit 1 (after adarshr's fix):
I now have white spaces. Only the first Satellite Entry is placed in the first line which shouldn't be.
<?xml version="1.0" encoding="UTF-8"?><Satellite SatelliteName="" XmlFileVersion="">
<test0>
<test1>
<test2>
<test3>
<test4>
<test5>
<test6>
<test7>
<test8>
<test9>blah</test9>
</test8>
</test7>
</test6>
</test5>
</test4>
</test3>
</test2>
</test1>
</test0>
<sdjklhewlkr/>
</Satellite>
Edit 2:
So the current state is that I now have whitespaces but I have no line feed after the XML declaration. How can I fix this?
try setting the indent amount like this:
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
I've played with Transformer, but never got it to work. I used the Xerces (Apache) library, which has always worked like a charm for me. Try something like
OutputFormat format = new OutputFormat(document);
format.setLineWidth(65);
format.setIndenting(true);
format.setIndent(2);
Writer outxml = new FileWriter(new File("out.xml"));
XMLSerializer serializer = new XMLSerializer(outxml, format);
serializer.serialize(document);
I had faced the same problem sometime back. The issue was that the implementation of the TransformerFactory or Transformer classes loaded was different from what Java intends it to be.
There was also a System property that we had to set in order to solve it. I will try and get that for you in a moment.
EDIT: Try this
System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.xsltc.trax.TransformerFactoryImpl");
I can give you 2 advice
1st
You can use xsl file for pretty output
2nd
I found interesting library ode-utils-XXX.jar
And you can just write like
String result = "";
try {
result = DOMUtils.prettyPrint(doc);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(result);
Can I print an XML document using escaped text instead of CDATA sections? For example, I want the output string as <sender>John Smith</sender> instead of <![CDATA[<sender>John Smith</sender>]]>. UPDATE: I know an XML document can be represented in both ways without any sematic difference, but I want to print the output string on screen.
Here is my code:
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "5");
StringWriter streamWriter = new StringWriter();
StreamResult streamResult = new StreamResult(streamWriter);
DOMSource source = new DOMSource(xml);
transformer.transform(source, streamResult);
return streamWriter.toString();
And here is the output:
<?xml version="1.0" encoding="UTF-8"?>
<VNET>
<ID>1</ID>
<UID>0</UID>
<NAME>ranged</NAME>
<TYPE>0</TYPE>
<BRIDGE>virbr0</BRIDGE>
<PUBLIC>1</PUBLIC>
<TEMPLATE>
<BRIDGE><![CDATA[virbr0]]></BRIDGE>
<NAME><![CDATA[ranged]]></NAME>
<NETWORK_ADDRESS><![CDATA[192.168.0.0]]></NETWORK_ADDRESS>
<NETWORK_SIZE><![CDATA[c]]></NETWORK_SIZE>
<TYPE><![CDATA[ranged]]></TYPE>
</TEMPLATE>
<LEASES/>
</VNET>
Thanks a lot.
Both XMLs (CDATA and with > etc.) are equivalent. An XML parser will read the character data in the same way and produce the same string. So it doesn't matter which is used; just leave it however the XML generator does it.
I'd like to serialize some simple data model into xml, I've been using the standard java.org.w3c -related code (see below), the indentation is better than no "OutputKeys.INDENT", yet there is one little thing that remains - proper indentation for child elements.
I know that this has been asked before on stackoverflow , yet that configuration did not work for me, this is the code I'm using :
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
doc = addItemsToDocument(doc);
// The addItemsToDocument method adds childElements to the document.
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute("indent-number", new Integer(4));
// switching to setAttribute("indent-number", 4); doesn't help
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(outFile);
// outFile is a regular File outFile = new File("some/path/foo.xml");
transformer.transform(source, result);
The output produced is :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<stuffcontainer>
<stuff description="something" duration="240" title="abc">
<otherstuff />
</stuff>
</stuffcontainer>
Whereas I would want it (for more clarity) like :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<stuffcontainer>
<stuff description="something" duration="240" title="abc">
<otherstuff />
</stuff>
</stuffcontainer>
I was just wondering if there is a way of doing this, make it properly indented for the child elements.
Thank you in advance !
Happy Easter coding :-) !
If the Transformer implementation you're using is Xalan-J, then you should be able to use:
transformer.setOutputProperty(
"{http://xml.apache.org/xslt}indent-amount", "5");
See also: http://xml.apache.org/xalan-j/usagepatterns.html
import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory
transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "4");
Document doc;
.....
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(doc), new StreamResult(new File("filename.xml")));
transformer.transform(new DOMSource(doc), new StreamResult(System.out));