RSS reader vs BOM error - java

I'm trying to read in an RSS Feed/XML file into my application. The problem is that there's a BOM (Byte Order Mark) that my inputStream doesn't like and it throws an error which throws another error and everything dies.
Here's the method:
private Document getDomFromXMLString(String xml) {
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
doc = db.parse(is);
} catch (Exception e) {
e.printStackTrace();
}
return doc;
}
So I'm trying to figure out how to effectively skip the BOM and input the rest of the file

If you have a character stream, and a String is, then skipping the BOM is as easy as stripping the first character, which is the BOM:
if (xml.charAt(0) == '\ufeff')
xml = xml.substring(1);
What you should really do, though, is ask the source to fix its feed; the BOM shouldn't be there in the first place.

Related

JAVA how to find and delete the structure of sentences?

I have a xml file, and its structure is like this.
<?xml version="1.0" encoding="MS949"?>
<pmd-cpd>
<duplication lines="123" tokens"123">
<file line="1" path="..">
<file line="1" path="..">
<codefragment><![CDATA[........]]></codefragment>
</duplication>
<duplication>
...
</duplication>
</pmd-cpd>
I want to delete 'codefragment' node, because my parser make an error 'invalid XML character(0x1). '
My parsing code is like this,
private void parseXML(File f){
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
Document document = null;
try {
builder = factory.newDocumentBuilder();
document = builder.parse(f);
}catch(...)
The error happens in document = builder.parse(f); so I cannot use parser to delete the codefragment node.
This is why I want to delete these lines without the parser.
How can I delete this node without the parser...?
This is a followup answer to OP's self-answer, and the comment I made to that answer. Here's the recap, plus some extra:
Never do String += String in a loop. Use StringBuilder.
Read the XML in blocks, not lines.
Don't use String.replaceAll(). It has to recompile the regex every time, a regex you already have. Use Matcher.replaceAll().
Remember to close() the Reader. Better yet, use try-with-resources.
No need to save the clean XML back out, just use it directly.
Since XML is usually in UTF-8, read the file as UTF-8.
Don't print and ignore errors. Let caller handle errors.
private static void parseXML(File f) throws IOException, ParserConfigurationException, SAXException {
StringBuilder xml = new StringBuilder();
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f),
StandardCharsets.UTF_8))) {
Pattern badChars = Pattern.compile("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]+");
char[] cbuf = new char[1024];
for (int len; (len = in.read(cbuf)) != -1; )
xml.append(badChars.matcher(CharBuffer.wrap(cbuf, 0, len)).replaceAll(""));
}
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
Document document = domBuilder.parse(new InputSource(new StringReader(xml.toString())));
// insert code using DOM here
}
How I solved this problem was, to remove the bad characters such as x01, save as new XML file, and then parse the new file.
Because I could not even parse my old xml file, I could not remove the node with parser.
So removing invalid character and saving as a new file code was like this.
//save the xml string as a new file.
public static Document stringToDom(String xmlSource)
throws SAXException, ParserConfigurationException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new InputSource(new StringReader(xmlSource)));
}
//get the file and remove bad characters in it
private static void cleanString(File fileName) {
try {
BufferedReader in = new BufferedReader(new FileReader(fileName));
String xmlLines, cleanXMLString="";
Pattern p = null;
Matcher m = null;
p = Pattern.compile("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]");
while (((xmlLines = in.readLine()) != null)){
m = p.matcher(xmlLines);
if (m.find()){
cleanXMLString = cleanXMLString + xmlLines.replaceAll("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]", "")+"\n";
}else
cleanXMLString = cleanXMLString + xmlLines+"\n";
}
Document doc = stringToDom(cleanXMLString);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("\\new\\"+fileName.getName()));
transformer.transform(source, result);
} catch (IOException | SAXException | ParserConfigurationException | TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Maybe, that's not good method since it takes quite long time for even a small file(under 5MB).
But if your file is small, you can try this...

Converting XML to document in java creates null document

I'm trying to parse xml, downloaded from the web, in java, following examples from here (stackoverflow) and other sources.
First I pack the xml in a string:
String xml = getXML(url, logger);
If I printout the xml string at this point:
System.out.println("XML " + xml);
I get a printout of the xml so I'm assuming there is no fault up to this point.
Then I try to create a document that I can evaluate:
InputSource is= new InputSource(new StringReader(xml));
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
If I print out the document here:
System.out.println("Doc: " + doc);
I get:
Doc: [#document: null]
When I later try to evaluate expressions with Xpath I get java.lang.NullPointerException and also when just trying to get the length of the root:
System.out.println("Root length " + rootNode.getLength());
which leaves me to believe the document (and later the node) is truly null.
When I try to print out the Input Source or the Node I get eg.
Input Source: org.xml.sax.InputSource#29453f44
which I don't know how to interpret.
Can any one see what I've done wrong or suggest a way forward?
Thanks in advance.
You may need another way to render the document as a string.
For JDOM:
public static String toString(final Document document) {
try {
final ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
final XMLOutputter outp = new XMLOutputter();
outp.output(document, out);
final String string = out.toString("UTF-8");
return string;
}
catch (final Exception e) {
throw new IllegalStateException("Cannot stringify document.", e);
}
}
The output
org.xml.sax.InputSource#29453f44
simply is the class name + the hash code of the instance (as defined in the Object class). It indicates that the class of the instance has toString not overridden.

Comparing of two XML DOC is getting fail because docs is comimg from two source

I have converted a string to an XML document using the code below:
String xmlStr = "<msg><uuid>12345</uuid></msg>"
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlStr)));
return doc;
} catch (Exception e) {
throw new RuntimeException(e);
}
Then I converted an XML file to a document with the following:
File file = new File("src/test/resources/xmlForJunitTest.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document expectedDoc = db.parse(file);
Finally I compare the two documents:
Document actualDoc = XmlUtils.convertStringToDocument(xmlString);
Diff myDiff = new Diff(expectedDoc, actualDoc);
assert (myDiff.similar());
This test passes using an XML file (xmlForJunitTest.xml) formatted like so:
<msg><uuid>12345</uuid></msg>
And it fails with this:
<msg>
<uuid>12345</uuid>
</msg>
Please you can suggest why this failure occurs, and what the solution is?
The assertion fails because one document includes whitespace, and the other doesn't. I believe you need to look at the normalizeWhitespace flag in XmlUnit (assuming that's what you're using).

Cannot create XML Document from String

I am trying to create an org.w3c.dom.Document form an XML string. I am using this How to convert string to xml file in java as a basis. I am not getting an exception, the problem is that my document is always null. The XML is system generated and well formed. I wish to convert it to a Document object so that I can add new Nodes etc.
public static org.w3c.dom.Document stringToXML(String xmlSource) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream input = IOUtils.toInputStream(xmlSource); //uses Apache commons to obtain InputStream
BOMInputStream bomIn = new BOMInputStream(input); //create BOMInputStream from InputStream
InputSource is = new InputSource(bomIn); // InputSource with BOM removed
Document document = builder.parse(new InputSource(new StringReader(xmlSource)));
Document document2 = builder.parse(is);
System.out.println("Document=" + document.getDoctype()); // always null
System.out.println("Document2=" + document2.getDoctype()); // always null
return document;
}
I have tried these things: I created a BOMInputStream thinking that a BOM was causing the conversion to fail. I thought that this was my issue but passing the BOMInputStream to the InputSource doesn't make a difference. I have even tried passing a literal String of simple XML and nothing but null. The toString method returns [#document:null]
I am using Xpages, a JSF implementation that uses Java 6. Full name of Document class used to avoid confusion with Xpage related class of the same name.
Don't rely on what toString is telling you. It is providing diagnostic information that it thinks is useful about the current class, which is, in this case, nothing more then...
"["+getNodeName()+": "+getNodeValue()+"]";
Which isn't going to help you. Instead, you will need to try and transform the model back into a String, for example...
String text
= "<fruit>"
+ "<banana>yellow</banana>"
+ "<orange>orange</orange>"
+ "<pear>yellow</pear>"
+ "</fruit>";
InputStream is = null;
try {
is = new ByteArrayInputStream(text.getBytes());
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(is);
System.out.println("Document=" + document.toString()); // always null
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");
ByteArrayOutputStream os = null;
try {
os = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(document);
StreamResult sr = new StreamResult(os);
tf.transform(domSource, sr);
System.out.println(new String(os.toByteArray()));
} finally {
try {
os.close();
} finally {
}
}
} catch (ParserConfigurationException | SAXException | IOException | TransformerConfigurationException exp) {
exp.printStackTrace();
} catch (TransformerException exp) {
exp.printStackTrace();
} finally {
try {
is.close();
} catch (Exception e) {
}
}
Which outputs...
Document=[#document: null]
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<fruit>
<banana>yellow</banana>
<orange>orange</orange>
<pear>yellow</pear>
</fruit>
You can try using this: http://www.wissel.net/blog/downloads/SHWL-8MRM36/$File/SimpleXMLDoc.java

How to turn a string into an XML file? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Writing to a XML file in Java
I have below XML text as a string.
<someNode>
<id>A124</id>
<status>404</status>
<message>No data</message>
</someNode>
I have above XML data as a String. Is it possible to convert the text into an XML file and archive the generated XML file?
Thanks!
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.parse(new InputSource(new StringReader(theString)));
public class StringToXML {
public static void main(String[] args) {
String xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"></soap:Envelope>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try
{
builder = factory.newDocumentBuilder();
// Use String reader
Document document = builder.parse( new InputSource(
new StringReader( xmlString ) ) );
TransformerFactory tranFactory = TransformerFactory.newInstance();
Transformer aTransformer = tranFactory.newTransformer();
Source src = new DOMSource( document );
Result dest = new StreamResult( new File( "xmlFileName.xml" ) );
aTransformer.transform( src, dest );
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This information is helpful.
Thanks,
Pavan
Its simple as that:
String text = "<your><xml>data</xml></your>";
Writer writer = new FileWriter("/tmp/filename.xml");
writer.write(text);
writer.flush();
writer.close();
You can, use the java.io.FileWriter to save your file.
String fileData = "<sample><xml>data</xml></sample>";
File outputFile = new File("someFile.xml");
BufferedWriter bw = null;
try{
bw = new BufferedWriter(new FileWriter(outputFile));
bw.write(fileData);
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try{bw.close();}catch(Exception e){}
}
In case you need to manipulate the xml do like Kazekage Gaara said:
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.parse(new InputSource(new StringReader(theString)));
And to save you can do as I said above. To transform the document back to string:
fileData = doc.toString();
I would recommend using commons-io. It has a single method that will do everything you need.
Code would look something like
FileUtils.writeStringToFile(new File("filename.xml"), xml);

Categories

Resources