Format XML file in java - java

I already created an xml, and i was obliged to modify it using PrintWriter Class. (copying line by line the xml file and modify what i need) but i lost my indentation.
i tried this :
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new InputStreamReader(new FileInputStream(
"notes.xml"))));
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.setOutputProperty(OutputKeys.METHOD, "xml");
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
xformer.setOutputProperty("b;http://xml.apache.org/xsltd;indent-amount", "4");
//xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
Source source = new DOMSource(document);
Result result = new StreamResult(new File("notes.xml"));
xformer.transform(source, result);
but this isn't working : having an exception in the third line :
[Fatal Error] :3:6537: XML document structures must start and end within the same entity.
org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 6537; XML document structures must start and end within the same entity.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:257)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
So, Is there a way to format an already created XML file in java ?

Related

Prevent transformer.transform( source, result ) from escaping special character

I'm updating node and text content of the xml using DOM parser. To save that DOM parser I'm using transformer.transform method.
Below is the sample code.
String xmlText = "<uc>abcd><name>mine</name>efgh\netg<tag>sd</tag></uc>";
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputSource inStream = new InputSource();
inStream.setCharacterStream(new StringReader(xmlText));
Document document = documentBuilder.parse(inStream);
Node node = document.getDocumentElement();
node.normalize();
NodeList childNodes = node.getChildNodes();
for(int i=0; i<childNodes.getLength(); i++) {
if(childNodes.item(i).getNodeType() == Node.TEXT_NODE) {
System.out.println(childNodes.item(i).getTextContent());
childNodes.item(i).setTextContent("123>");
}
}
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "US-ASCII");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource( document );
OutputStream xml = new ByteArrayOutputStream();
StreamResult result = new StreamResult( xml );
transformer.transform( source, result );
String formattedXml = xml.toString();
System.out.println(formattedXml);
Since my updated document is having text content like ">", transformer.transform method is changing it to &g t;
Is there a way to get the output without escaping special characters.
I can't use other parser because of some project constraints.
I can't use StringEscapeUtils.unescapeXml(). The reason is xml can have &g t;. If i use this utility method, &g t; which was originally present in the xml will also get changed.
So i want a mechanism which will not escape any special character.
The transformer you create with
Transformer transformer = tFactory.newTransformer();
is initialized with a default stylesheed that implements the identity transformation. That means it will simply serialize your DOM to a well-formed XML document. Output escaping is automatically applied where necessary.
If you want better control over the output, and possibly generate something that does not adhere to XML document structures, you can use a custom stylesheet that switches the output method to text. This way you control more of the structure but can do more mistakes in the XML area.
More information at
https://docs.oracle.com/en/java/javase/11/docs/api/java.xml/javax/xml/transform/TransformerFactory.html#newTransformer()
https://www.w3.org/TR/xslt20/#element-output

How to create line breaks in xml using java

I want to create an xml file with line breaks, looking somewhat like this:
<Instrument currencyId="THB"
disabledCount="0"
hasBeenEnabledOnce="TRUE"
</Instrument>
Using this code I got close but all attributes seems to be end up on the same row:
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("Instrument");
doc.appendChild(rootElement);
Instrument.setAttribute("currencyId", "THB");
Instrument.setAttribute("disabledCount", "0");
Instrument.setAttribute("hasBeenEnabledOnce", "TRUE");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("C:\\file.xml"));
transformer.transform(source, result);
I get the following result:
<Instrument currencyId="THB" disabledCount="0" hasBeenEnabledOnce="TRUE"
How can I add linebreaks between the attributes??
just a slight notice, I thought that transformer.setOutputProperies could solve the problem, by searching for similar problems I ended up with "OutputKeys.INDENT", "yes", and the indent-amount -> "4". But nothing's changed.
Doesnt matter if I open the file in notepad++ or as a webpage.

XML file saved from Swing application

I'm developing a Java Swing Application, and I want to create objects and save them in a XML file, with the information that a user writes in some text fields.
How can I save that data into a XML file, to form those objects?
You can write your own XML-Writer to write out objects/text to a XML file. For example using DOM
public boolean writeCommonSettingsFromGUI()
{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("NAME_OF_A_ELEMENT");
doc.appendChild(rootElement);
Element xmlInfo = doc.createElement("NAME_OF_ANOTHER_ELEMENT");
xmlInfo.setTextContent("YOUR_CONTENT_TO_SET_FOR_THIS_ELEMENT");
rootElement.appendChild(xmlInfo);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "5");
transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
DOMSource source = new DOMSource(doc);
StreamResult result = null;
result = new StreamResult(new File("FILE_PATH_WHERE_TO_SAVE_YOUR_XML"));
transformer.transform(source, result);
return true;
}
use castor framework, you can map your java class to xml file and vice versa

Issues with reading and writing an XML file in Java

Am using DocumentBuilderFactory to read an XML file and write the same file with different file name. Here's my code :
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse(new InputSource("internal.xml"));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(dom);
StreamResult result = new StreamResult(new File("newInternal.xml"));
transformer.transform(source, result);
System.out.println("File Saved!!!");
But am experiencing error in 'newInternal.xml' file. It's saving with '&lt' , '&gt' in the new file. May I know the issue with the above code ?
But it's working fine when I changed the Xml version from 1.1 to 1.0.
Your code is correct.
On correct XML syntax, you write < to represent a < and > to represent a >.
These escapings exists to ease their utilization, because the characters are used on the XML syntax itself.
This question has the list of such characters.

How to create attribute (xmlns:xsd) to XML node in Java?

I am currently creating an XML document in Java. The document should have the following structure:
<?xml version="1.0" ?>
<Cancelacion xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
RfcEmisor="VSI850514HX4"
Fecha="2011-11-23T17:25:06"
xmlns="http://cancelacfd.sat.gob.mx">
<Folios>
<UUID>BD6CA3B1-E565-4985-88A9-694A6DD48448</UUID>
</Folios>
</Cancelacion>
I want to know if there is a special way to create the attributes with form xmlns:xsd?
I am currently declaring this attribute like this:
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
doc.setXmlVersion("1.0");
doc.setXmlStandalone(true);
Element cancelacion = doc.createElement("Cancelacion");
cancelacion.setAttribute("xmlns", "http://cancelacfd.sat.gob.mx");
cancelacion.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
cancelacion.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
cancelacion.setAttribute("RfcEmisor", rfc);
cancelacion.setAttribute("Fecha", fecha);
The solution my problem is to write the code as follows:
//Crear un document XML vacĂ­o
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
dbfac.setNamespaceAware(true);
DocumentBuilder docBuilder;
docBuilder = dbfac.newDocumentBuilder();
DOMImplementation domImpl = docBuilder.getDOMImplementation();
Document doc = domImpl.createDocument("http://cancelacfd.sat.gob.mx", "Cancelacion", null);
doc.setXmlVersion("1.0");
doc.setXmlStandalone(true);
Element cancelacion = doc.getDocumentElement();
cancelacion.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xsd","http://www.w3.org/2001/XMLSchema");
cancelacion.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
cancelacion.setAttribute("RfcEmisor", rfc);
cancelacion.setAttribute("Fecha", fecha);
Element folios = doc.createElement("Folios");
cancelacion.appendChild(folios);
for (int i=0; i<uuid.length; i++) {
Element u = doc.createElement("UUID");
u.setTextContent(uuid[i]);
folios.appendChild(u);
}
Why should the document have your proposed structure? You're declaring namespaces with prefixes, but your example output doesn't include any elements in those namespaces. Those declarations are therefore unnecessary.
First, understand that xmlns (or xmlns:prefix) is the reserved XML pseudo-attribute for declaring namespaces. It's not a normal attribute. Second, the location of namespace declarations in the document shouldn't concern you, as long as you're creating elements in the desired namespaces in the first place.
Let the serializer decide where to place the namespace declarations.
Register an element in the correct namespace like this:
Element cancelacion = doc.createElementNS(
"http://cancelacfd.sat.gob.mx", "Cancelacion");
doc.appendChild(cancelacion);
Element child = doc.createElementNS("http://cancelacfd.sat.gob.mx",
"SomeChild");
cancelacion.appendChild(child);
When serialized:
DOMSource domSource = new DOMSource(doc);
StreamResult streamResult = new StreamResult(System.out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.transform(domSource, streamResult);
Result:
<Cancelacion xmlns="http://cancelacfd.sat.gob.mx">
<SomeChild/>
</Cancelacion>
Notice that Cancelacion and SomeChild were created in exactly the same way, but only Cancelacion contains the namespace declaration (because the declaration applies for all descendants). The serializer handled this for us.
Warning: What follows is a hack. I do not recommend using it. It will probably get you into trouble. You should probably stop reading. But...if you have no choice, it might work.
If you're desperate, you could manually splice in the unused namespaces. (Treating XML as a string is almost always a bad idea.)
First, save the result in an OutputStream that can be converted to a String:
ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(doc);
StreamResult streamResult = new StreamResult(out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.transform(domSource, streamResult);
Then jam the namespace declarations in there without any regard for what is good, right, and decent:
String[] parts = out.toString().split("\\\">", 2);
String result = parts[0] +
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + parts[1];
xmlns:xsd is not an attribute, its a namespace declaration.
The DOM should create these declarations as and when they are needed.
Using the createElementNS and createAttributeNS methods will result in namespace declarations being created, but you need to understand XML namespaces.
In your example, the namespaces bound to xsd and xsi are not used so are superfluous. However, the Cancelacion element is in the default namespace which is defined by the xmlns="http://cancelacfd.sat.gob.mx" declaration in the XML you have provided.
So you should use:
doc.createElementNS("http://cancelacfd.sat.gob.mx", "Cancelacion");
to create that. Note that the namespace prefix (or lack thereof) is irrelevant as far as the meaning of the document is concerned.
in my code, I wrote :
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
Element spectraexchage = document.createElementNS("http://www.lstelcom.com/Schema/SPECTRAexchange", "SPECTRAEXCHANGE");
spectraexchage.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
spectraexchage.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
spectraexchage.setAttribute("version", "2.4.28");
document.appendChild(spectraexchage);
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
output :
<SPECTRAEXCHANGE xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4.28" xmlns="http://www.lstelcom.com/Schema/SPECTRAexchange">

Categories

Resources