Transformer escapes CR - java

Suggest the following program:
import java.io.StringReader;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class CrDemo {
public static void main(String[] args) throws Exception {
final String xml = "<a>foo
\nbar
\n</a>";
final TransformerFactory tf = TransformerFactory.newInstance();
final Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "no");
t.setOutputProperty(OutputKeys.STANDALONE, "yes");
t.transform(new StreamSource(new StringReader(xml)), new StreamResult(System.out));
}
}
The output looks like this:
<a>foo
bar
</a>
Is it possible to prevent the Transformer from escaping CR?

If the input XML contained literal CR characters, they would be removed during parsing. XML parsers normalize line endings to a single NL character; but this doesn't apply if the CR is escaped as 
.
So if a text node contains a CR character, the XSLT processor assumes you have worked hard to put it there and that you really want it, and it therefore outputs it in such a way that it will survive round-tripping where the resulting serialized output is re-processed by an XML parser.
Of course, you can get rid of CR characters in your XSLT code, just as you can get rid of any other characters. But it won't happen automatically.

Related

Java - Extract child elements

I am new in Java and need to parse the below XML file
<foo>
<foo1>
<tag1>1</tag1>
<tag2>2</tag2>
</foo1>
<foo2>
<element1>aaa</element1>
<element1>bbb</element2>
</foo2>
</foo>
I need
<foo1>
<tag1>1</tag1>
<tag2>2</tag2>
</foo1>
<foo2>
<element1>aaa</element1>
<element1>bbb</element2>
</foo2>
as output. I was able to get the values of nodes but not desired output. Please help me out.. Thanks.
OK, I think I got it. Here's the code with documentation:
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
// parse input XML file into Document
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse("C://Temp/xx.xml");
// build a formatted XML String
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(doc), result);
String xmlString = result.getWriter().toString();
// Split the formatted-XML-String according to new-line
String lines[] = xmlString.split("\\r?\\n");
// rebuild the String, skipping undesired lines
xmlString = "" ;
String newLine = String.format("%n");
for (int i = 2 ; i < lines.length-1 ; i++) {
xmlString += lines[i] + newLine;
}
System.out.println(xmlString);
Since in your case, you desire an invalid XML as output, I suggest you don't parse the XML file. Just read the entire file line-by-line and build the desired String by skipping first and last lines

Adding linebreak in xml file before root node

I am trying to add line break after my comments above the root node in XML document.
I need something like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--DO NOT EDIT THIS FILE-->
<projects>
</projects>
But What I was able to get is this(Line break inside the root but I need line break after the comment):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--DO NOT EDIT THIS FILE--><projects>
</projects>
I need to add the line break just after my comment. Is there a way to do this?
My code:
import java.io.File;
import java.io.FileInputStream;
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.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
public class XMLNewLine {
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("Adding comment..");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
DocumentBuilder db;
try {
Document doc;
StreamResult result;
result = new StreamResult(new File("abc.xml"));
db = dbf.newDocumentBuilder();
doc = db.parse(new FileInputStream(new File("abc.xml")));
Element element = doc.getDocumentElement();
Text lineBreak = doc.createTextNode("\n");
element.appendChild(lineBreak);
Comment comment = doc
.createComment("DO NOT EDIT THIS FILE");
element.getParentNode().insertBefore(comment, element);
doc.getDocumentElement().normalize();
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
}
You basically want a text node containing a line break after the comment node.
Element docElem = doc.getDocumentElement();
doc.insertBefore(doc.createComment("DO NOT EDIT THIS FILE"), docElem);
doc.insertBefore(doc.createTextNode("\\n"), docElem);
EDIT: It seems that appending even whitespace-only text nodes is not allowed at the root node of an org.w3c.dom.Document. This is 100% formally correct, but also unhelpful.
The way comments are rendered in the output of the Transformer is determined by the serializer it uses (there are different serializers for HTML, XML and plain text outputs). In the built-in XML serializer the end of a comment is defined as --> - without a newline.
Since the internals of javax.xml.transform.Transformer are hard-wired, the serializers are not public API and the class is marked as final, overriding that behavior or setting a custom serializer is impossible.
In other words, you are out of luck adding your line break in a clean way.
You can, however, safely add it in a slightly unclean way:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
FileInputStream inputXml = new FileInputStream(new File("input.xml"));
Document doc = db.parse(inputXml);
// add the comment node
doc.insertBefore(doc.createComment("THIS IS A COMMENT"), doc.getDocumentElement());
StringWriter outputXmlStringWriter = new StringWriter();
Transformer transformer = transformerFactory.newTransformer();
// "xml" + "UTF-8" "include XML declaration" is the default anyway, but let's be explicit
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(doc), new StreamResult(outputXmlStringWriter));
// now insert our newline into the string & write an UTF-8 file
String outputXmlString = outputXmlStringWriter.toString()
.replaceFirst("<!--", "\n<!--").replaceFirst("-->", "-->\n");
FileOutputStream outputXml = new FileOutputStream(new File("output.xml"));
outputXml.write(outputXmlString.getBytes("UTF-8"));
Doing search-and-replace operations on XML strings is highly discouraged in general, but in this case there is little that can go wrong.
Revisiting this after some time because I had the same issue. I found another solution that does not need to buffer the output in a String:
Write only the XML-declaration by passing an empty document. This will also append a linebreak.
Write the document content without XML-declaration
Code:
StreamResult streamResult = new StreamResult(writer);
// output XML declaration with an empty document
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.transform(new DOMSource(), streamResult);
// output the document without XML declaration
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(doc), streamResult);
You can achieve this by not adding the comment node to your document, but instead partially transforming your document. First transform your own XML processing instruction and comment separately, and then the rest of document:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new FileInputStream(new File("abc.xml")));
Result output = new StreamResult(new File("abc.xml"));
Source input = new DOMSource(doc);
// xml processing instruction and comment node
ProcessingInstruction xmlpi = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"");
Comment comment = doc.createComment("DO NOT EDIT THIS FILE");
// first transform the processing instruction and comment
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(xmlpi), output);
transformer.transform(new DOMSource(comment), output);
// then the document
transformer.transform(input, output);
There is a JDK bug concerning this. It was not fixed (as you would expect) because that would likely cause many problems to users' existing applications.
Adding the following output property fixes this:
transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
Had the same issue.
I solved it by putting the comment inside the root element.
Not exactly the same, but I think acceptable.
This is my solution. I just take writer and write to it declaration and the header comment. After that I disable declaration in transformer this way
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
All code:
public static String xmlToTree(String xml, String headerComment) {
try (StringReader reader = new StringReader(xml)) {
StreamResult result = new StreamResult(new StringWriter());
result.getWriter().write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
result.getWriter().write(headerComment + "\n");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
StreamSource source = new StreamSource(reader);
transformer.transform(source, result);
String xmlTree = result.getWriter().toString();
return xmlTree;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}

Dynamically insert an XML Element into a text node

I'm writing a program in Java where the ultimate goal is to create an XML file from user inputs.
I'm able to predict where almost all of the elements need to be, with one exception.
Any one sentence the user inputs is put into its own Callout tag:
<Callout>The user entered some text.</Callout>
If the sentence contains the phrase "User Guide", the program needs to automatically surround those two words with this XML tag:
<BookTitle></BookTitle>
For example, the initial tag looks like this:
<Callout>Save the User Guide</Callout>
The end result should be:
<Callout>Save the <BookTitle>User Guide</BookTitle>.</Callout>
Note that the term "User Guide" could appear in any location within the "Callout" tag.
I'm not sure how to dynamically add a tag into the middle of a text node. Is that even possible? I tried the solution found here (Convert String XML fragment to Document Node in Java)
but to no avail. I'm using org.w3c.dom to create the elements, nodes, etc.
Don't know exactly how you are constructing your XML document, I assumed the use of some kind of DOM.
This is a VERY simple example of a proof-of-concept. It borrows very heavily from library code, so it may be a little bloated in places, but the basic idea should be reasonable...
Basically, it searches a String for a given token (User Guide) in this case and splits the original text around it, appending #text nodes and <BookTitle> nodes appropriately...
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
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.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
public class Main {
public static final String BOOK_TITLE = "User Guide";
public static void main(String[] args) {
Document doc = null;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = doc.createElement("root");
doc.appendChild(root);
// Create callout node...
Element callOut = doc.createElement("CallOut");
// Get the user input...
String text = "This is an example of a User Guide for you to read";
// Does it contain our marker...?
if (text.contains(BOOK_TITLE)) {
// While the text contains the mark, continue looping...
while (text.contains(BOOK_TITLE)) {
// Get the text before the marker...
String prefix = text.substring(0, text.indexOf(BOOK_TITLE));
// Get the text after the marker...
text = text.substring(text.indexOf(BOOK_TITLE) + BOOK_TITLE.length());
// If there is text before the marker, append it to the call out node
if (prefix.length() > 0) {
Text textNode = doc.createTextNode(prefix);
callOut.appendChild(textNode);
}
// Append the book title node...
Element bookTitle = doc.createElement("BookTitle");
bookTitle.setTextContent(BOOK_TITLE);
callOut.appendChild(bookTitle);
}
// If there is any text remaining, append it to the call out node...
if (text.length() > 0) {
Text textNode = doc.createTextNode(text);
callOut.appendChild(textNode);
}
} else {
// No marker, append the text to the call out node..
Text textNode = doc.createTextNode(text);
callOut.appendChild(textNode);
}
// This will dump the result for you to test....
root.appendChild(callOut);
ByteArrayOutputStream baos = null;
OutputStreamWriter osw = null;
try {
baos = new ByteArrayOutputStream();
osw = new OutputStreamWriter(baos);
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.setOutputProperty(OutputKeys.METHOD, "xml");
tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource domSource = new DOMSource(doc);
StreamResult sr = new StreamResult(osw);
tf.transform(domSource, sr);
osw.flush();
baos.flush();
System.out.println(new String(baos.toByteArray()));
} finally {
try {
baos.close();
} catch (Exception exp) {
}
}
} catch (IOException | TransformerException | ParserConfigurationException ex) {
ex.printStackTrace();
}
}
}
People will have different approaches to dealing with XML manipulations. The variety of answers to this question is proof enough of this. While using regex and raw text manipulation might be good for one off fixes and hacks if you want a good and maintainable solution you should use an XML API.
My example below does what is asked, however it should be noted that I didn't check for any pathological inputs like ("" as the search string) or deal with XML namespaces. Those things can be added easily enough.
See comments in the code for description of how it works.
Input (test.xml):
<Callouts>
<Callout>Save the User Guide.</Callout>
</Callouts>
Program
package com.stackoverflow._18774666;
import java.net.URL;
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.NodeList;
import org.w3c.dom.Text;
public class InsertElementInTextNode {
/**
* Replace text content of child text nodes of a parent element that
* matches a search string. The text is replace by an element named with the
* given name and has it's text content set equal to the search string.
*
* #param parent
* The element to search child text nodes of.
* #param elementName
* The name of the element to insert.
* #param text
* The text to replace with an element with same text content.
*/
public static void replaceTextWithElement(Element parent, String elementName, String text){
NodeList children = parent.getChildNodes();
Text cursor;
Element insertedElement;
int index;
/* Iterate children of the given element. */
for(int i = 0; i < children.getLength(); i++ ){
/* Check if this child is a text node. Ignore otherwise. */
if(children.item(i) instanceof Text){
cursor = (Text) children.item(i);
/* If the entire text node is equal to the search string,
* then we can replace it directly. Else we have split it.*/
if(text.equals(cursor.getData())){
/* Replace the text node with an element */
insertedElement = parent.getOwnerDocument().createElement(elementName);
insertedElement.setTextContent(text);
parent.replaceChild(insertedElement, cursor);
} else {
/* Check to see if the search string exists in this text node. Ignore otherwise.*/
index = cursor.getData().indexOf(text);
if(index != -1){
/* Replace the matched substring with an empty string.*/
cursor.replaceData(index, text.length(), "");
/* Create element to be inserted, and set the text content. */
insertedElement = parent.getOwnerDocument().createElement(elementName);
insertedElement.setTextContent(text);
/* Split the text node and insert the element in the middle. */
parent.insertBefore(insertedElement, cursor.splitText(index));
}
}
}
}
}
public static void main(String[] args) throws Exception {
/* Location of our XML document. */
URL xmlSource = InsertElementInTextNode.class.getResource("test.xml");
/* Parse with DOM in to a Document */
Document xmlDoc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(xmlSource.openStream());
/* Find our interesting elements. */
NodeList nodes = xmlDoc.getElementsByTagName("Callout");
/* Iterate through our interesting elements and check their content.*/
Element cursor;
for(int i = 0; i < nodes.getLength(); i++ ){
if(nodes.item(i) instanceof Element){
cursor = (Element) nodes.item(i);
replaceTextWithElement(cursor, "BookTitle", "User Guide");
}
}
/* Setup to output result. */
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
/* Printing result to stdout. */
transformer.transform(new DOMSource(xmlDoc),
new StreamResult(System.out));
}
}
Output (stdout):
<Callouts>
<Callout>Save the <BookTitle>User Guide</BookTitle>.</Callout>
</Callouts>
first get the user input and compare it to user guide, if it's true then surround it with title.
String UserInput = null;
UserInput = #getUserType.toString();
if(UserInput.equals("User Guide")){
UserInput = "<BookTitle>"+UserInput+"<BookTitle>";
}else{
//do things if it's false not User Guide
}
public static void main(String[] args) {
String str = "This is my User Guide dude";
boolean bTest = str.contains("User Guide");
if (bTest) {
int index1 = str.indexOf("User Guide");
String sub = str.substring(index1, index1 + 10);
sub = "<BookTitle>" + sub + "</BookTitle>";
String result = str.replace("User Guide", sub);
System.out.println(result);
}
}
OUTPUT:
This is my <BookTitle>User Guide</BookTitle> dude
I think this will point you in the right direction at least.

DOM parser in java not encoding quotes in UTF-8

I am trying to use the code available from this tutorial :http://www.mkyong.com/java/how-to-create-xml-file-in-java-dom/
I've pasted the code below as well, the problem it seems to encode all the predef characters <,> and & etc. but not single or double quotes (" and '). I'd really appreciate a fix. Also the code below has an edit to make the resultant xml appear properly formatted
More specifically:
import java.io.File;
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.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class WriteXMLFile {
public static void main(String argv[]) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("company");
doc.appendChild(rootElement);
// staff elements
Element staff = doc.createElement("Staff");
rootElement.appendChild(staff);
// set attribute to staff element
Attr attr = doc.createAttribute("id");
attr.setValue("1");
staff.setAttributeNode(attr);
// shorten way
// staff.setAttribute("id", "1");
// firstname elements
Element firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode("yong"));
staff.appendChild(firstname);
// lastname elements
Element lastname = doc.createElement("lastname");
lastname.appendChild(doc.createTextNode("mook kim"));
staff.appendChild(lastname);
// nickname elements
Element nickname = doc.createElement("nickname");
nickname.appendChild(doc.createTextNode("mkyong"));
staff.appendChild(nickname);
// salary elements
Element salary = doc.createElement("salary");
salary.appendChild(doc.createTextNode("100000"));
staff.appendChild(salary);
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("C:\\file.xml"));
// Output to console for testing
// StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
System.out.println("File saved!");
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
}
}
}
I think your code works fine. Put a double quote in an attribute value and see what happens.
Read section 2.4 of the XML specification. Production 14 of the grammar
[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
tells you that character data can be any (valid XML) character except '<' and '&' (or the ']]>' sequence). It is not strictly necessary to escape '>', although recommended.

XML Node to String in Java

I came across this piece of Java function to convert an XML node to a Java String representation:
private String nodeToString(Node node) {
StringWriter sw = new StringWriter();
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(new DOMSource(node), new StreamResult(sw));
} catch (TransformerException te) {
System.out.println("nodeToString Transformer Exception");
}
return sw.toString();
}
It looks straightforward in that it wants the output string doesn't have any XML declaration and it must contain indentation.
But I wonder how the actual output should be, suppose I have an XML node:
<p><media type="audio" id="au008093" rights="wbowned">
<title>Bee buzz</title>
</media>Most other kinds of bees live alone instead of in a colony. These bees make
tunnels in wood or in the ground. The queen makes her own nest.</p>
Could I assume the resulting String after applying the above transformation is:
"media type="audio" id="au008093" rights="wbowned" title Bee buzz title /media"
I want to test it myself, but I have no idea on how to represent this XML node in the way this function actually wants.
I am bit confused, and thanks in advance for the generous help.
All important has already been said. I tried to compile the following code.
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
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.Node;
public class Test {
public static void main(String[] args) throws Exception {
String s =
"<p>" +
" <media type=\"audio\" id=\"au008093\" rights=\"wbowned\">" +
" <title>Bee buzz</title>" +
" " +
" Most other kinds of bees live alone instead of in a colony." +
" These bees make tunnels in wood or in the ground." +
" The queen makes her own nest." +
"</p>";
InputStream is = new ByteArrayInputStream(s.getBytes());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document d = db.parse(is);
Node rootElement = d.getDocumentElement();
System.out.println(nodeToString(rootElement));
}
private static String nodeToString(Node node) {
StringWriter sw = new StringWriter();
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(new DOMSource(node), new StreamResult(sw));
} catch (TransformerException te) {
System.out.println("nodeToString Transformer Exception");
}
return sw.toString();
}
}
And it produced the following output:
<p> <media id="au008093" rights="wbowned" type="audio"> <title>Bee buzz</title> </media> Most other kinds of bees live alone instead of in a colony. These bees make tunnels in wood or in the ground. The queen makes her own nest.</p>
You can further tweak it by yourself. Good luck!
You have an XML respesentation in a DOM tree.
For example you have opened an XML file and you have passed it in the DOM parser.
As a result a DOM tree in memory with your XML is created.
Now you can only access the XML info via traversal of the DOM tree.
If you need though, a String representation of the XML info of the DOM tree you use a transformation.
This happens since it is not possible to get the String representation directly from a DOM tree.
So if for example as Node node you pass in nodeToString is the root element of the XML doc then the result is a String containing the original XML data.
The tags will still be there. I.e. you will have a valid XML representation. Only this time will be in a String variable.
For example:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document xmlDoc = parser.parse(file);//file has the xml
String xml = nodeToString(xmlDoc.getDocumentElement());//pass in the root
//xml has the xml info. E.g no xml declaration. Add it
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> + xml;//bad to append this way...
System.out.println("XML is:"+xml);
DISCLAIMER: Did not even attempt to compile code. Hopefully you understand what you have to do

Categories