--- /dev/null
+package org.simantics.interop.xmlio;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.File;\r
+import java.io.FileReader;\r
+import java.io.Reader;\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+\r
+import javax.xml.parsers.SAXParser;\r
+import javax.xml.parsers.SAXParserFactory;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.DelayedWriteRequest;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.SessionGarbageCollection;\r
+import org.simantics.layer0.Layer0;\r
+import org.xml.sax.Attributes;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.XMLReader;\r
+import org.xml.sax.helpers.DefaultHandler;\r
+\r
+\r
+\r
+public class LoadXML {\r
+\r
+ private Session session;\r
+ private Resource resultRoot;\r
+ \r
+ private File file;\r
+ \r
+ private Map<Integer,Resource> idMap = new HashMap<Integer, Resource>();\r
+ \r
+ //private Map<String,Resource> uriMap = new HashMap<String, Resource>();\r
+ \r
+ private WriteGraph graph;\r
+ private Layer0 l0;\r
+ private LoadRule rule;\r
+ \r
+ private int resources;\r
+ private int statements;\r
+ \r
+ public LoadXML(Session session, File file) {\r
+ this.session = session;\r
+ this.file = file;\r
+ this.rule = new DefaultLoadRule();\r
+ }\r
+ \r
+ public void setRule(LoadRule rule) {\r
+ this.rule = rule;\r
+ }\r
+ \r
+ public void load(final Resource subj, final Resource pred) throws Exception {\r
+ resources = 0;\r
+ statements = 0;\r
+ // TODO : switch to Delayed if possible\r
+ // Delayed Write Graph in 1.6 does not seem to support converting virtual Resources to real Resources!\r
+ \r
+ session.syncRequest(new DelayedWriteRequest() {\r
+ //session.syncRequest(new WriteRequest() {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ LoadXML.this.graph = graph;\r
+ l0 = Layer0.getInstance(graph);\r
+ try {\r
+ XMLParser parser = new XMLParser();\r
+ parser.parse(file.getAbsolutePath());\r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ } finally {\r
+ resultRoot = idMap.get(0);\r
+ graph.claim(subj, pred, resultRoot);\r
+ idMap.clear();\r
+ }\r
+ }\r
+ });\r
+ \r
+ System.out.println("Imported " + statements + " Statements, " + resources + " Resources.");\r
+ }\r
+ \r
+ \r
+// public Resource getResult() {\r
+// return resultRoot;\r
+// }\r
+ \r
+ protected Resource getResource(ReadGraph graph, String uri) throws DatabaseException {\r
+ return rule.getResource(graph, uri);\r
+ }\r
+ \r
+ protected Object createValue(ReadGraph graph, List<String> value, List<String> types) throws DatabaseException {\r
+ return rule.createValue(graph, value, types);\r
+ }\r
+ \r
+ protected void initializeWithBundles(ReadGraph graph, List<Bundle> bundles) throws DatabaseException {\r
+ rule.initializeWithBundles(graph, bundles);\r
+ }\r
+ \r
+ \r
+ public class XMLParser extends DefaultHandler implements Serializable {\r
+\r
+ private static final long serialVersionUID = -4995836637014958966L;\r
+ \r
+ private Stack<Element> current = new Stack<Element>();\r
+ \r
+ private void loadElement(Element element) throws SAXException{\r
+ String name = element.qName;\r
+ if ("graphexport".equals(name))\r
+ return;\r
+ if ("graphbundles".equals(name)) {\r
+ element.setData(new ArrayList<Bundle>());\r
+ return;\r
+ }\r
+ if ("bundle".equals(name))\r
+ return;\r
+ if ("resource".equals(name)) {\r
+ element.setData(new Res());\r
+ return;\r
+ }\r
+ if ("type".equals(name)) {\r
+ return;\r
+ }\r
+ if ("statement".equals(name))\r
+ return;\r
+ \r
+ }\r
+ \r
+ private void handleElement(Stack<Element> parents, Element element) throws SAXException{\r
+ try {\r
+ String elementName = element.qName;\r
+ if ("graphexport".equals(elementName))\r
+ return;\r
+ if ("graphbundles".equals(elementName)) {\r
+ List<Bundle> list = (List<Bundle>)element.getData();\r
+ initializeWithBundles(graph, list);\r
+ element.setData(null);\r
+ return;\r
+ }\r
+ if ("bundle".equals(elementName)) {\r
+ List<Bundle> list = (List<Bundle>)parents.peek().getData();\r
+ String name = null;\r
+ String versionId = null;\r
+ for (Attribute a : element.getAttributes()) {\r
+ if ("name".equals(a.qName))\r
+ name = a.value;\r
+ if ("versionid".equals(a.qName))\r
+ versionId = a.value;\r
+ } \r
+ list.add(new Bundle(name,versionId));\r
+ return;\r
+ }\r
+ if ("resource".equals(elementName)) {\r
+ Res res = (Res)element.getData();\r
+ boolean rel = false;\r
+ String uri = null;\r
+ int id = -1;\r
+ Resource r = null;\r
+ for (Attribute a : element.getAttributes()) {\r
+ if ("id".equals(a.qName))\r
+ id = Integer.parseInt(a.value);\r
+ if ("rel".equals(a.qName))\r
+ rel = "true".equals(a.value);\r
+ if ("uri".equals(a.qName))\r
+ uri = a.value;\r
+ } \r
+ if (rel) {\r
+ r = getResource(graph, uri);\r
+ } else {\r
+ \r
+ r = graph.newResource();\r
+ for (String typeUri : res.types) {\r
+ Resource type =getResource(graph, typeUri);\r
+ graph.claim(r, l0.InstanceOf, type);\r
+ }\r
+ \r
+ if (res.values.size() > 0 ) {\r
+ Object valObj = createValue(graph, res.values, res.types);\r
+ graph.claimValue(r, valObj);\r
+ }\r
+ }\r
+ if (id == -1)\r
+ throw new SAXException("Resource id missing");\r
+ idMap.put(id, r);\r
+ \r
+ res.types.clear();\r
+ res.values.clear();\r
+ element.setData(null);\r
+ resources++;\r
+ return;\r
+ }\r
+ if ("type".equals(elementName)) {\r
+ Element parent = parents.peek();\r
+ Res res = (Res)parent.getData();\r
+ String uri = null;\r
+ for (Attribute a : element.getAttributes()) {\r
+ if ("uri".equals(a.qName))\r
+ uri = a.value;\r
+ } \r
+ if (uri != null)\r
+ res.types.add(uri);\r
+ \r
+ return;\r
+ }\r
+ if ("value".equals(elementName)) {\r
+ Element parent = parents.peek();\r
+ Res res = (Res)parent.getData();\r
+ String value = null;\r
+ for (Attribute a : element.getAttributes()) {\r
+ if ("value".equals(a.qName))\r
+ value = a.value;\r
+ } \r
+ if (value != null)\r
+ res.values.add(value);\r
+ \r
+ return;\r
+ }\r
+ if ("statement".equals(elementName)) {\r
+ int subjId = -1;\r
+ int predId = -1;\r
+ int objId = -1;\r
+ for (Attribute a : element.getAttributes()) {\r
+ if ("subject".equals(a.qName))\r
+ subjId = Integer.parseInt(a.value);\r
+ if ("predicate".equals(a.qName))\r
+ predId = Integer.parseInt(a.value);\r
+ if ("object".equals(a.qName))\r
+ objId = Integer.parseInt(a.value);\r
+ } \r
+ \r
+ graph.claim(idMap.get(subjId), idMap.get(predId), idMap.get(objId));\r
+ statements++;\r
+ if (statements % 10000 == 0) {\r
+ System.out.println("Imported " + statements + " Statements, " + resources + " Resources..");\r
+ //SessionGarbageCollection.gc(graph, 0, -1);\r
+ }\r
+ return;\r
+ }\r
+ \r
+ } catch (DatabaseException e) {\r
+ throw new SAXException(e);\r
+ }\r
+ }\r
+ \r
+ public void done() {\r
+ \r
+ }\r
+ \r
+ public void parse(String filename) throws Exception {\r
+ SAXParserFactory spf = SAXParserFactory.newInstance();\r
+ SAXParser saxParser = spf.newSAXParser();\r
+ \r
+ XMLReader reader = saxParser.getXMLReader();\r
+ Reader file = new BufferedReader(new FileReader(filename));\r
+ reader.setContentHandler(this);\r
+ reader.parse(new InputSource(file));\r
+ done();\r
+ }\r
+ \r
+ @Override\r
+ public void startElement(String uri, String localName, String name,\r
+ Attributes attributes) throws SAXException {\r
+ Element e = new Element(uri,localName,name,attributes);\r
+ current.push(e);\r
+ //texts.push(new String());\r
+ loadElement(e);\r
+ }\r
+ \r
+ @Override\r
+ public void endElement(String uri, String localName, String name)\r
+ throws SAXException {\r
+ Element e = null;\r
+ if (!current.empty()) {\r
+ e = current.pop();\r
+ }\r
+ if (e != null) {\r
+ handleElement(current,e);\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ public class Attribute {\r
+ public String localName;\r
+ public String qName;\r
+ public String uri;\r
+ public String value;\r
+ \r
+ public Attribute(String localName, String qName, String uri, String value) {\r
+ this.localName = localName;\r
+ this.qName = qName;\r
+ this.uri = uri;\r
+ this.value = value;\r
+ }\r
+ }\r
+ \r
+ public class Element implements Serializable {\r
+ private static final long serialVersionUID = -5207502156942818875L;\r
+ String uri;\r
+ String localName;\r
+ String qName;\r
+ List<Attribute> attributes = new ArrayList<Attribute>();\r
+ \r
+ public Element(String uri, String localName, String qName, Attributes attributes) {\r
+ this.uri = uri;\r
+ this.localName = localName;\r
+ this.qName = qName;\r
+ for (int i = 0; i < attributes.getLength(); i++) {\r
+ this.attributes.add(new Attribute(attributes.getLocalName(i),attributes.getQName(i),attributes.getURI(i),attributes.getValue(i)));\r
+ }\r
+ }\r
+\r
+ public String getUri() {\r
+ return uri;\r
+ }\r
+\r
+ public String getLocalName() {\r
+ return localName;\r
+ }\r
+\r
+ public String getQName() {\r
+ return qName;\r
+ }\r
+\r
+ public List<Attribute> getAttributes() {\r
+ return attributes;\r
+ }\r
+\r
+ private Object data;\r
+ \r
+ public void setData(Object data) {\r
+ this.data = data;\r
+ }\r
+ \r
+ public Object getData() {\r
+ return data;\r
+ }\r
+\r
+ }\r
+ class Res {\r
+ \r
+ List<String> types = new ArrayList<String>();\r
+ List<String> values = new ArrayList<String>();\r
+ }\r
+ \r
+ public static class Bundle {\r
+ String name;\r
+ String versionId;\r
+ public Bundle(String name, String versionId) {\r
+ super();\r
+ this.name = name;\r
+ this.versionId = versionId;\r
+ }\r
+ \r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ public String getVersionId() {\r
+ return versionId;\r
+ }\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.interop.xmlio;\r
+\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.OutputStreamWriter;\r
+import java.io.PrintWriter;\r
+import java.io.Writer;\r
+import java.util.Arrays;\r
+import java.util.Calendar;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+\r
+import org.apache.xml.serialize.OutputFormat;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.DatabaseManagementResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.xml.sax.Attributes;\r
+import org.xml.sax.Locator;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.SAXParseException;\r
+import org.xml.sax.ext.LexicalHandler;\r
+import org.xml.sax.ext.Locator2;\r
+import org.xml.sax.helpers.AttributesImpl;\r
+import org.xml.sax.helpers.DefaultHandler;\r
+\r
+public class SaveXML extends DefaultHandler implements LexicalHandler {\r
+ \r
+ private Session session;\r
+ private Resource root;\r
+ private SaveRule saveRule;\r
+ \r
+ \r
+ private File file;\r
+ \r
+ private PrintWriter fOut;\r
+ /** Canonical output. */\r
+ protected boolean fCanonical = true;\r
+ /** Element depth. */\r
+ protected int fElementDepth;\r
+ \r
+ /** Document locator. */\r
+ protected Locator fLocator;\r
+ \r
+ /** Processing XML 1.1 document. */\r
+ protected boolean fXML11 = true;\r
+ \r
+ /** In CDATA section. */\r
+ protected boolean fInCDATA;\r
+ \r
+ \r
+ public SaveXML(Session session, Resource root, File file) {\r
+ this.session = session;\r
+ this.root = root;\r
+ this.file = file;\r
+ this.saveRule = new DependsOnSaveRule();\r
+ }\r
+ \r
+ public void setSaveRule(SaveRule saveRule) {\r
+ this.saveRule = saveRule;\r
+ }\r
+ \r
+ public void save() throws DatabaseException, IOException, SAXException {\r
+ fCanonical = false;\r
+ FileOutputStream fos = new FileOutputStream(file);\r
+ fOut = new PrintWriter(new OutputStreamWriter(fos, "UTF8"));\r
+ \r
+ startDocument();\r
+ fXML11 = true;\r
+ AttributesImpl attrs = new AttributesImpl();\r
+ addDate(attrs);\r
+ startElement("", "", "graphexport", attrs);\r
+ saveGraphBundles();\r
+ saveData();\r
+ endElement("", "", "graphexport");\r
+ endDocument();\r
+ fOut.close();\r
+ }\r
+ \r
+ private void addDate(AttributesImpl attrs) {\r
+ Calendar calendar = Calendar.getInstance();\r
+ int year = calendar.get(Calendar.YEAR);\r
+ int month = calendar.get(Calendar.MONTH) + 1;\r
+ int day = calendar.get(Calendar.DAY_OF_MONTH);\r
+ int hour = calendar.get(Calendar.HOUR_OF_DAY);\r
+ int min = calendar.get(Calendar.MINUTE);\r
+ int sec = calendar.get(Calendar.SECOND);\r
+ String date = "";\r
+ date += year;\r
+ date += "-";\r
+ if (month < 10)\r
+ date+="0";\r
+ date += month;\r
+ date += "-";\r
+ if (day < 10)\r
+ date+="0";\r
+ date += day;\r
+ date += "T";\r
+ if (hour < 10)\r
+ date+="0";\r
+ date += hour;\r
+ date += ":";\r
+ if (min < 10)\r
+ date+="0";\r
+ date += min;\r
+ date += ":";\r
+ if (sec < 10)\r
+ date+="0";\r
+ date += sec;\r
+ attrs.addAttribute("", "", "date", "CDATA", date);\r
+ }\r
+ \r
+ \r
+ Map<Resource,Integer> idMap = new HashMap<Resource, Integer>();\r
+ \r
+ Set<Resource> processed = new HashSet<Resource>();\r
+ Stack<Resource> stack = new Stack<Resource>();\r
+ Layer0 l0;\r
+ int statements = 0;\r
+ \r
+ private void saveData() throws DatabaseException {\r
+ idMap.clear();\r
+ processed.clear();\r
+ stack.clear();\r
+ statements = 0;\r
+ session.syncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ l0 = Layer0.getInstance(graph);\r
+ saveRule.init(graph);\r
+ stack.push(root);\r
+ }\r
+ });\r
+ try {\r
+ while (!stack.isEmpty()) {\r
+ session.syncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ \r
+ try {\r
+ \r
+ \r
+ AttributesImpl attrs = new AttributesImpl();\r
+ \r
+ \r
+ while (!stack.isEmpty()) {\r
+ Resource r = stack.pop();\r
+ if (processed.contains(r))\r
+ continue;\r
+ processed.add(r);\r
+ Collection<Statement> statement = graph.getStatements(r, l0.IsWeaklyRelatedTo);\r
+ boolean split = false;\r
+ for (Statement s : statement) { \r
+ if (s.isAsserted(r))\r
+ continue;\r
+ if (!saveRule.save(graph, s))\r
+ continue;\r
+ // System.out.println("Processing " + s.getSubject() + " " + s.getPredicate() + " " + s.getObject());\r
+ \r
+ statements++;\r
+ int sId = getId(graph, s.getSubject(),false);\r
+ int pId = getId(graph, s.getPredicate(),true);\r
+ int oId = getId(graph, s.getObject(),false);\r
+ attrs.clear();\r
+ attrs.addAttribute("", "", "subject", "CDATA", Integer.toString(sId));\r
+ attrs.addAttribute("", "", "predicate", "CDATA", Integer.toString(pId));\r
+ attrs.addAttribute("", "", "object", "CDATA", Integer.toString(oId));\r
+ startElement("", "", "statement", attrs);\r
+ endElement("", "", "statement");\r
+ if (!processed.contains(s.getObject()))\r
+ stack.push(s.getObject());\r
+ if (statements % 10000 == 0) {\r
+ System.out.println("Processed " + statements + " statements...");\r
+ split = true;\r
+ }\r
+ \r
+ }\r
+ if (split)\r
+ return;\r
+ \r
+ }\r
+ System.out.println("Done. Processed " + statements + " statements.");\r
+ } catch (SAXException e) {\r
+ throw new DatabaseException(e); \r
+ }\r
+ \r
+ }\r
+ });\r
+ \r
+ }\r
+ } finally {\r
+ idMap.clear();\r
+ processed.clear();\r
+ stack.clear();\r
+ }\r
+ \r
+}\r
+ \r
+ private int getId(ReadGraph g, Resource r, boolean rel) throws SAXException, DatabaseException {\r
+ Integer id = idMap.get(r);\r
+ if (id == null) {\r
+ id = idMap.size();\r
+ idMap.put(r, id);\r
+ AttributesImpl attrs = new AttributesImpl();\r
+ attrs.addAttribute("", "", "id", "CDATA", id.toString());\r
+ if (rel) {\r
+ attrs.addAttribute("", "", "rel", "CDATA", Boolean.TRUE.toString());\r
+ String uri = g.getPossibleURI(r);\r
+ if (uri != null)\r
+ attrs.addAttribute("", "", "uri", "CDATA", uri);\r
+ }\r
+ \r
+ startElement("", "", "resource", attrs);\r
+ if (!rel) {\r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ //Collection<Resource> types = g.getPrincipalTypes(r);\r
+ Collection<Resource> types = g.getObjects(r, l0.InstanceOf);\r
+ attrs.clear();\r
+ for (Resource type : types) {\r
+ String uri = g.getPossibleURI(type);\r
+ if (uri != null) {\r
+ attrs.addAttribute("", "", "uri", "CDATA", uri);\r
+ startElement("", "", "type", attrs);\r
+ endElement("", "", "type");\r
+ } else {\r
+ // TODO : handle URIless types.\r
+ throw new DatabaseException("Cannot resolve URI for type " + type + ", instance " + r); \r
+ }\r
+ }\r
+ }\r
+ if (g.hasValue(r)) {\r
+ // FIXME: does not handle arrays.\r
+ Object value = g.getValue(r);\r
+ \r
+ if (value instanceof Object[]) {\r
+ Object[] valuearray = (Object[])value;\r
+ for (Object o : valuearray) {\r
+ attrs.clear();\r
+ attrs.addAttribute("", "", "value", "CDATA", o.toString());\r
+ startElement("", "", "value", attrs);\r
+ endElement("", "", "value");\r
+ }\r
+ } else {\r
+ attrs.clear();\r
+ attrs.addAttribute("", "", "value", "CDATA", value.toString());\r
+ startElement("", "", "value", attrs);\r
+ endElement("", "", "value");\r
+ }\r
+ }\r
+ endElement("", "", "resource");\r
+ \r
+ }\r
+ return id;\r
+ }\r
+ \r
+ \r
+ private void saveGraphBundles() throws DatabaseException{\r
+ final Resource rootLibrary = session.getRootLibrary();\r
+ session.syncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ DatabaseManagementResource dm = DatabaseManagementResource.getInstance(graph);\r
+ Collection<Resource> objs = graph.getObjects(rootLibrary, l0.ConsistsOf);\r
+ Resource graphBundles = null;\r
+ for (Resource o : objs) {\r
+ if (isGraphBundleLib(graph, rootLibrary)) {\r
+ graphBundles = o;\r
+ break;\r
+ }\r
+ }\r
+ if (graphBundles == null)\r
+ graphBundles = dm.InstalledGraphBundles;\r
+ \r
+ objs = graph.getObjects(graphBundles, l0.ConsistsOf);\r
+ AttributesImpl attrs = new AttributesImpl();\r
+ try {\r
+ startElement("", "", "graphbundles", attrs);\r
+ for (Resource graphBundle : objs) {\r
+ if (!graph.isInstanceOf(graphBundle, dm.GraphBundle))\r
+ continue;\r
+ String name = graph.getRelatedValue(graphBundle, l0.HasName);\r
+ String versionId = graph.getRelatedValue(graphBundle, dm.HasVersionedId);\r
+ attrs.clear();\r
+ attrs.addAttribute("", "", "name", "CDATA", name);\r
+ attrs.addAttribute("", "", "versionid", "CDATA", versionId);\r
+ startElement("", "", "bundle", attrs);\r
+ endElement("", "", "bundle");\r
+ }\r
+ \r
+ endElement("", "", "graphbundles");\r
+ } catch (SAXException e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ }\r
+ });\r
+ }\r
+ \r
+ private boolean isGraphBundleLib(ReadGraph graph, Resource o) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ String name = graph.getPossibleRelatedValue(o, l0.HasName);\r
+ return "InstalledGraphBundles".equals(name);\r
+ }\r
+ \r
+ \r
+ \r
+ /** Set Document Locator. */\r
+ public void setDocumentLocator(Locator locator) {\r
+ fLocator = locator;\r
+ } // setDocumentLocator(Locator)\r
+ \r
+ /** Start document. */\r
+ public void startDocument() throws SAXException {\r
+\r
+ fElementDepth = 0;\r
+ fXML11 = false;\r
+ fInCDATA = false;\r
+ \r
+ } // startDocument()\r
+\r
+ /** Processing instruction. */\r
+ public void processingInstruction(String target, String data)\r
+ throws SAXException {\r
+\r
+ if (fElementDepth > 0) {\r
+ fOut.print("<?");\r
+ fOut.print(target);\r
+ if (data != null && data.length() > 0) {\r
+ fOut.print(' ');\r
+ fOut.print(data);\r
+ }\r
+ fOut.print("?>");\r
+ fOut.flush();\r
+ }\r
+\r
+ } // processingInstruction(String,String)\r
+\r
+ /** Start element. */\r
+ public void startElement(String uri, String local, String raw,\r
+ Attributes attrs) throws SAXException {\r
+\r
+ // Root Element\r
+ if (fElementDepth == 0) {\r
+ String encoding = "UTF-8";\r
+ if (fLocator != null) {\r
+ if (fLocator instanceof Locator2) {\r
+ Locator2 locator2 = (Locator2) fLocator;\r
+ fXML11 = "1.1".equals(locator2.getXMLVersion());\r
+ encoding = locator2.getEncoding();\r
+ if (encoding == null) {\r
+ encoding = "UTF-8";\r
+ }\r
+ }\r
+ fLocator = null;\r
+ }\r
+\r
+ // The XML declaration cannot be printed in startDocument because\r
+ // the version and encoding information reported by the Locator \r
+ // cannot be relied on until the next event after startDocument.\r
+ if (!fCanonical) {\r
+ fOut.print("<?xml version=\"");\r
+ fOut.print(fXML11 ? "1.1" : "1.0");\r
+ fOut.print("\" encoding=\"");\r
+ fOut.print(encoding);\r
+ fOut.println("\"?>");\r
+ fOut.flush();\r
+ }\r
+ }\r
+ \r
+ fElementDepth++;\r
+ fOut.print('<');\r
+ fOut.print(raw);\r
+ if (attrs != null) {\r
+ attrs = sortAttributes(attrs);\r
+ int len = attrs.getLength();\r
+ for (int i = 0; i < len; i++) {\r
+ fOut.print(' ');\r
+ fOut.print(attrs.getQName(i));\r
+ fOut.print("=\"");\r
+ normalizeAndPrint(attrs.getValue(i), true);\r
+ fOut.print('"');\r
+ }\r
+ }\r
+ //fOut.print('>');\r
+ fOut.print(">\n");\r
+ fOut.flush();\r
+\r
+ } // startElement(String,String,String,Attributes)\r
+\r
+ /** Characters. */\r
+ public void characters(char ch[], int start, int length)\r
+ throws SAXException {\r
+\r
+ if (!fInCDATA) {\r
+ normalizeAndPrint(ch, start, length, false);\r
+ }\r
+ else {\r
+ for (int i = 0; i < length; ++i) {\r
+ fOut.print(ch[start+i]);\r
+ }\r
+ }\r
+ fOut.flush();\r
+\r
+ } // characters(char[],int,int);\r
+\r
+ /** Ignorable whitespace. */\r
+ public void ignorableWhitespace(char ch[], int start, int length)\r
+ throws SAXException {\r
+\r
+ characters(ch, start, length);\r
+ fOut.flush();\r
+\r
+ } // ignorableWhitespace(char[],int,int);\r
+\r
+ /** End element. */\r
+ public void endElement(String uri, String local, String raw)\r
+ throws SAXException {\r
+\r
+ fElementDepth--;\r
+ fOut.print("</");\r
+ fOut.print(raw);\r
+ //fOut.print('>');\r
+ fOut.print(">\n");\r
+ fOut.flush();\r
+\r
+ } // endElement(String)\r
+\r
+ //\r
+ // ErrorHandler methods\r
+ //\r
+\r
+ /** Warning. */\r
+ public void warning(SAXParseException ex) throws SAXException {\r
+ printError("Warning", ex);\r
+ } // warning(SAXParseException)\r
+\r
+ /** Error. */\r
+ public void error(SAXParseException ex) throws SAXException {\r
+ printError("Error", ex);\r
+ } // error(SAXParseException)\r
+\r
+ /** Fatal error. */\r
+ public void fatalError(SAXParseException ex) throws SAXException {\r
+ printError("Fatal Error", ex);\r
+ throw ex;\r
+ } // fatalError(SAXParseException)\r
+\r
+ //\r
+ // LexicalHandler methods\r
+ //\r
+\r
+ /** Start DTD. */\r
+ public void startDTD(String name, String publicId, String systemId)\r
+ throws SAXException {\r
+ } // startDTD(String,String,String)\r
+\r
+ /** End DTD. */\r
+ public void endDTD() throws SAXException {\r
+ } // endDTD()\r
+\r
+ /** Start entity. */\r
+ public void startEntity(String name) throws SAXException {\r
+ } // startEntity(String)\r
+\r
+ /** End entity. */\r
+ public void endEntity(String name) throws SAXException {\r
+ } // endEntity(String)\r
+\r
+ /** Start CDATA section. */\r
+ public void startCDATA() throws SAXException {\r
+ if (!fCanonical) {\r
+ fOut.print("<![CDATA[");\r
+ fInCDATA = true;\r
+ }\r
+ } // startCDATA()\r
+\r
+ /** End CDATA section. */\r
+ public void endCDATA() throws SAXException {\r
+ if (!fCanonical) {\r
+ fInCDATA = false;\r
+ fOut.print("]]>");\r
+ }\r
+ } // endCDATA()\r
+\r
+ /** Comment. */\r
+ public void comment(char ch[], int start, int length) throws SAXException {\r
+ if (!fCanonical && fElementDepth > 0) {\r
+ fOut.print("<!--");\r
+ for (int i = 0; i < length; ++i) {\r
+ fOut.print(ch[start+i]);\r
+ }\r
+ //fOut.print("-->");\r
+ fOut.print("-->\n");\r
+ fOut.flush();\r
+ }\r
+ } // comment(char[],int,int)\r
+\r
+ //\r
+ // Protected methods\r
+ //\r
+\r
+ /** Returns a sorted list of attributes. */\r
+ protected Attributes sortAttributes(Attributes attrs) {\r
+\r
+ return attrs;\r
+// AttributesImpl attributes = new AttributesImpl();\r
+//\r
+// int len = (attrs != null) ? attrs.getLength() : 0;\r
+// for (int i = 0; i < len; i++) {\r
+// String name = attrs.getQName(i);\r
+// int count = attributes.getLength();\r
+// int j = 0;\r
+// while (j < count) {\r
+// if (name.compareTo(attributes.getQName(j)) < 0) {\r
+// break;\r
+// }\r
+// j++;\r
+// }\r
+// //attributes.insertAttributeAt(j, name, attrs.getType(i),attrs.getValue(i));\r
+// attributes.setAttribute(j, attrs.getURI(i), attrs.getLocalName(i), name, attrs.getType(i), attrs.getValue(i));\r
+// }\r
+//\r
+// return attributes;\r
+\r
+ } // sortAttributes(AttributeList):AttributeList\r
+\r
+ /** Normalizes and prints the given string. */\r
+ protected void normalizeAndPrint(String s, boolean isAttValue) {\r
+\r
+ int len = (s != null) ? s.length() : 0;\r
+ for (int i = 0; i < len; i++) {\r
+ char c = s.charAt(i);\r
+ normalizeAndPrint(c, isAttValue);\r
+ }\r
+\r
+ } // normalizeAndPrint(String,boolean)\r
+\r
+ /** Normalizes and prints the given array of characters. */\r
+ protected void normalizeAndPrint(char[] ch, int offset, int length, boolean isAttValue) {\r
+ for (int i = 0; i < length; i++) {\r
+ normalizeAndPrint(ch[offset + i], isAttValue);\r
+ }\r
+ } // normalizeAndPrint(char[],int,int,boolean)\r
+\r
+ /** Normalizes and print the given character. */\r
+ protected void normalizeAndPrint(char c, boolean isAttValue) {\r
+\r
+ switch (c) {\r
+ case '<': {\r
+ fOut.print("<");\r
+ break;\r
+ }\r
+ case '>': {\r
+ fOut.print(">");\r
+ break;\r
+ }\r
+ case '&': {\r
+ fOut.print("&");\r
+ break;\r
+ }\r
+ case '"': {\r
+ // A '"' that appears in character data \r
+ // does not need to be escaped.\r
+ if (isAttValue) {\r
+ fOut.print(""");\r
+ }\r
+ else {\r
+ fOut.print("\"");\r
+ }\r
+ break;\r
+ }\r
+ case '\r': {\r
+ // If CR is part of the document's content, it\r
+ // must not be printed as a literal otherwise\r
+ // it would be normalized to LF when the document\r
+ // is reparsed.\r
+ fOut.print("
");\r
+ break;\r
+ }\r
+ case '\n': {\r
+ if (fCanonical) {\r
+ fOut.print("
");\r
+ break;\r
+ }\r
+ // else, default print char\r
+ }\r
+ default: {\r
+ // In XML 1.1, control chars in the ranges [#x1-#x1F, #x7F-#x9F] must be escaped.\r
+ //\r
+ // Escape space characters that would be normalized to #x20 in attribute values\r
+ // when the document is reparsed.\r
+ //\r
+ // Escape NEL (0x85) and LSEP (0x2028) that appear in content \r
+ // if the document is XML 1.1, since they would be normalized to LF \r
+ // when the document is reparsed.\r
+ if (fXML11 && ((c >= 0x01 && c <= 0x1F && c != 0x09 && c != 0x0A) \r
+ || (c >= 0x7F && c <= 0x9F) || c == 0x2028)\r
+ || isAttValue && (c == 0x09 || c == 0x0A)) {\r
+ fOut.print("&#x");\r
+ fOut.print(Integer.toHexString(c).toUpperCase());\r
+ fOut.print(";");\r
+ }\r
+ else {\r
+ fOut.print(c);\r
+ } \r
+ }\r
+ }\r
+ } // normalizeAndPrint(char,boolean)\r
+\r
+ /** Prints the error message. */\r
+ protected void printError(String type, SAXParseException ex) {\r
+\r
+ System.err.print("[");\r
+ System.err.print(type);\r
+ System.err.print("] ");\r
+ String systemId = ex.getSystemId();\r
+ if (systemId != null) {\r
+ int index = systemId.lastIndexOf('/');\r
+ if (index != -1)\r
+ systemId = systemId.substring(index + 1);\r
+ System.err.print(systemId);\r
+ }\r
+ System.err.print(':');\r
+ System.err.print(ex.getLineNumber());\r
+ System.err.print(':');\r
+ System.err.print(ex.getColumnNumber());\r
+ System.err.print(": ");\r
+ System.err.print(ex.getMessage());\r
+ System.err.println();\r
+ System.err.flush();\r
+\r
+ } // printError(String,SAXParseException)\r
+\r
+}\r