2 * This file is part of NeverNote
3 * Copyright 2009 Randy Baumgarte
5 * This file may be licensed under the terms of of the
6 * GNU General Public License Version 2 (the ``GPL'').
8 * Software distributed under the License is distributed
9 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
10 * express or implied. See the GPL for the specific language
11 * governing rights and limitations.
13 * You should have received a copy of the GPL along with this
14 * program. If not, go to http://www.gnu.org/licenses/gpl.html
15 * or write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 package cx.fbn.nevernote.xml;
22 import java.io.IOException;
23 import java.io.StringReader;
25 import javax.xml.parsers.ParserConfigurationException;
26 import javax.xml.parsers.SAXParser;
27 import javax.xml.parsers.SAXParserFactory;
29 import org.xml.sax.InputSource;
30 import org.xml.sax.SAXException;
31 import org.xml.sax.SAXParseException;
33 import cx.fbn.nevernote.Global;
35 public class XMLNoteRepair {
36 public boolean saveInvalidXML;
38 public String parse(String xmlData, boolean validate) {
39 saveInvalidXML = false;
40 InputSource is = new InputSource();
41 is.setCharacterStream(new StringReader(xmlData));
42 XMLNoteRepairHandler handler = new XMLNoteRepairHandler();
44 // Replace DTD with local copy in case we are not connected
45 File dtdFile = Global.getFileManager().getXMLDirFile("enml2.dtd");
46 String dtd = dtdFile.toURI().toString();
47 xmlData = xmlData.replace("<!DOCTYPE en-note SYSTEM \'http://xml.evernote.com/pub/enml2.dtd'>",
48 "<!DOCTYPE en-note SYSTEM \"" +dtd +"\">");
49 xmlData = xmlData.replace("<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">",
50 "<!DOCTYPE en-note SYSTEM \"" +dtd +"\">");
52 handler.setXml(xmlData);
53 is.setCharacterStream(new StringReader(handler.getXml()));
55 boolean fixed = false;
60 while (!fixed && i<max) {
63 SAXParserFactory factory = SAXParserFactory.newInstance();
64 factory.setValidating(validate);
65 SAXParser parser = factory.newSAXParser();
66 parser.parse(is, handler);
68 } catch (EnmlException e) {
69 String message = e.getMessage();
70 saveInvalidXML = true;
71 //System.out.println("ENML Exception: " +message);
72 boolean found = false;
73 int endAttribute = message.indexOf(" must be declared for element type ");
74 if (message.startsWith("Attribute ") && endAttribute > -1) {
75 String attribute = message.substring(11, endAttribute-1);
76 String element = message.substring(message.indexOf("\"", endAttribute+3));
77 element = element.replace("\"", "");
78 element = element.substring(0,element.length()-1);
79 Global.addInvalidAttribute(element, attribute);
80 handler.stripAttribute(attribute, e.getLineNumber(), e.getColumnNumber());
81 is.setCharacterStream(new StringReader(handler.getXml()));
84 int endElement = message.indexOf(" must be declared.");
85 if (message.startsWith("Element type") && endElement > -1) {
86 String element = message.substring(14,endElement-1);
87 Global.addInvalidElement(element);
88 handler.renameElement(element, e.getLineNumber(), e.getColumnNumber());
89 is.setCharacterStream(new StringReader(handler.getXml()));
93 System.err.println("New enml validation error: " +e.getMessage() +" Line:" +e.getLineNumber() +" Column:" +e.getColumnNumber());
94 } catch (SAXParseException e) {
95 System.err.println("SAXParse Exception - Attempt #"+i +" "+e.getMessage());
96 handler.repair(e.getLineNumber(), e.getColumnNumber());
97 is.setCharacterStream(new StringReader(handler.getXml()));
99 System.err.println("Error validating ENML2 DTD");
102 } catch (SAXException e) {
103 System.err.append("SAXException");
105 } catch (ParserConfigurationException e) {
106 System.err.println("Parser Config Error");
108 } catch (IOException e) {
109 System.err.println("IO Exception");
116 // Replace DTD with online copy
117 xmlData = handler.getXml();
118 xmlData = xmlData.replace("<!DOCTYPE en-note SYSTEM \"" +dtd +"\">", "<!DOCTYPE en-note SYSTEM \'http://xml.evernote.com/pub/enml2.dtd'>");