Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have XML file like below
<?xml version="1.0" encoding="utf-8"?>
<Movies>
<servername>
raaja
</servername>
<moviename>
xyz
</moviename>
<city>
Hyd
</city>
<theatername>
abc
</theatername>
<noofreels>
16
</noofreels>
<aspectratio>
216
</aspectratio>
</Movies>
I want the values of tags servername and theatername. Rest I dont want. How to get these using java. Is it possible to get the value using tagnames.
One way to accomplish this is to use the DOM parser included with the JDK. For example:
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
...
// Creates a new DOM parser instance.
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
// Parses XML and creates a DOM document object.
// The XML variable is your XML document above stored as a string, but you could
// easily read the contents from a file or database too.
Document document = documentBuilder.parse(new InputSource(new StringReader(XML)));
// Get the text content of <theatername> using the DOM API and print it to stdout.
String theaterName = document.getElementsByTagName("theatername").item(0).getTextContent().trim();
System.out.println(theaterName);
Using StAX:
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(new StringReader(XML));
String theaterName = null;
while (xmlStreamReader.hasNext()) {
if (xmlStreamReader.next() == XMLStreamConstants.START_ELEMENT) {
if ("theatername".equals(xmlStreamReader.getLocalName())) {
theaterName = xmlStreamReader.getElementText().trim();
}
}
}
System.out.println(theaterName);
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;
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How could I read Java Console Output into a String buffer
I know how to read input from user and put it on XML file.Here is the sample:
from http://www.mkyong.com/java/how-to-create-xml-file-in-java-dom/
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();
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();
}
}
}
but my question is how to read the output from the console in java and print it in specified XML file.
I am not sure what exactly you mean by "reading the output from the console" but you can intercept calls to System.out by using http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#setOut%28java.io.PrintStream%29.
If you elaborate more on what you are trying to do I can be more specific.
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.
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