]> gerrit.simantics Code Review - simantics/interop.git/blobdiff - org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java
Export XML Namespaces
[simantics/interop.git] / org.simantics.xml.sax.base / src / org / simantics / xml / sax / base / XMLParser.java
index be8fef042f4cb882d97d73aac759c5661ef63bb9..01b8deba7b3ad341cba064836ab78417977bf62f 100644 (file)
@@ -28,18 +28,41 @@ import org.xml.sax.helpers.DefaultHandler;
 \r
 public class XMLParser extends DefaultHandler implements Serializable {\r
 \r
+       public static String PLUGIN_ID = "org.simantics.xml.sax.base";\r
+       public static String XML_NAMESPACE_REF = "xmlns";\r
+       \r
        private static final long serialVersionUID = 7360740940824360338L;\r
        private static final boolean debug = false;\r
+       \r
        private ILogger logger;\r
+       private WriteGraph graph;\r
        private Resource root;\r
-       private Deque<Element> current = new ArrayDeque<Element>();\r
+       private String schemaURI;\r
+       private Deque<ParserElement> current = new ArrayDeque<ParserElement>();\r
        private Map<String, XMLElementParser> parsers = new HashMap<String, XMLElementParser>();\r
-       private WriteGraph graph;\r
-       \r
        private Map<Class<? extends XMLElementParser>, XMLElementParser> namedParsers = new HashMap<Class<? extends XMLElementParser>, XMLElementParser>();\r
+       private Map<String, XMLParser> subParsers = new HashMap<String, XMLParser>();\r
+       \r
+       public XMLParser() {\r
        \r
-       public XMLParser(WriteGraph graph) {\r
+       }\r
+       \r
+       public WriteGraph getGraph() {\r
+               return graph;\r
+       }\r
+       \r
+       public void setGraph(WriteGraph graph) {\r
                this.graph = graph;\r
+               for (XMLParser p : subParsers.values())\r
+                       p.setGraph(graph);\r
+       }\r
+       \r
+       public String getSchemaURI() {\r
+               return schemaURI;\r
+       }\r
+       \r
+       public void setSchemaURI(String schemaURI) {\r
+               this.schemaURI = schemaURI;\r
        }\r
        \r
        public void add(XMLElementParser parser) {\r
@@ -48,16 +71,25 @@ public class XMLParser extends DefaultHandler implements Serializable {
                namedParsers.put(parser.getClass(), parser);\r
        }\r
        \r
+       public void add(XMLParser parser) {\r
+               subParsers.put(parser.getSchemaURI(), parser);\r
+       }\r
        \r
-       private List<Element> idReferenceElements = new ArrayList<Element>();\r
-       private void loadElement(Deque<Element> parents, Element element) throws SAXException{\r
+       private List<ParserElement> idReferenceElements = new ArrayList<ParserElement>();\r
+       private void loadElement(Deque<ParserElement> parents, ParserElement element) throws SAXException{\r
                XMLElementParser parser = null;\r
-               Element parent = null;\r
+               ParserElement parent = null;\r
                if (parents.size() > 0) {\r
                        parent = parents.peek();\r
-                       if (parent.getParser() instanceof XMLElementNamedChildParser) {\r
+                       // check for assigned subparser\r
+                       if (parent.getXMLParser() != null && parent.getXMLParser() != this) {\r
+                               element.setXMLParser(parent.getXMLParser());\r
+                               parent.getXMLParser().loadElement(parents, element);\r
+                               return;\r
+                       }\r
+                       if (parent.getElementParser() instanceof XMLElementNamedChildParser) {\r
                                // use parent's named child parser if it is supported\r
-                               Class<? extends XMLElementParser> parserClass = ((XMLElementNamedChildParser)parent.getParser()).getParser(parsers,parent,element);\r
+                               Class<? extends XMLElementParser> parserClass = ((XMLElementNamedChildParser)parent.getElementParser()).getParser(parsers,parent,element);\r
                                if (parserClass != null) {\r
                                        parser = namedParsers.get(parserClass);\r
                                        if (parser == null) {\r
@@ -65,7 +97,7 @@ public class XMLParser extends DefaultHandler implements Serializable {
                                                        parser = parserClass.newInstance();\r
                                                        namedParsers.put(parserClass, parser);\r
                                                } catch (IllegalAccessException | InstantiationException e) {\r
-                                                       String err = "Element parsers must have accessible default constructor";\r
+                                                       String err = "Error processing " + parserClass.getName() + " : element parsers must have accessible default constructor";\r
                                                        logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
                                                        throw new SAXException(err, e);\r
                                                }\r
@@ -88,30 +120,38 @@ public class XMLParser extends DefaultHandler implements Serializable {
                                element.setData(parser.create(graph, element));\r
                                if (parser instanceof IDReferenceParser)\r
                                        idReferenceElements.add(element);\r
-                               element.setParser(parser);\r
+                               element.setElementParser(parser);\r
                        } catch (DatabaseException e) {\r
                                throw new SAXException(e);\r
                        }\r
                } else {\r
-                       if (parent == null && parents.size() > 0)\r
-                               parent = parents.peek();\r
-                       String err = "Unknown element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None");\r
-                       logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
-                       if (debug) System.err.println(err);\r
+                       // check for schema reference attempt to locate subparser for it.\r
+                       Attribute schemaRef = element.getAttribute(XML_NAMESPACE_REF);\r
+                       if (schemaRef != null && subParsers.containsKey(schemaRef.value)) {\r
+                               XMLParser subParser = subParsers.get(schemaRef.value);\r
+                               subParser.loadElement(parents, element);\r
+                               element.setXMLParser(subParser);\r
+                       } else {\r
+                               if (parent == null && parents.size() > 0)\r
+                                       parent = parents.peek();\r
+                               String err = "Unknown element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None");\r
+                               logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
+                               if (debug) System.err.println(err);\r
+                       }\r
                }\r
        }\r
        \r
-       private Map<String, Element> idMap = new HashMap<String, Element>();\r
+       private Map<String, ParserElement> idMap = new HashMap<String, ParserElement>();\r
        \r
-       private void handleElement(Deque<Element> parents, Element element) throws SAXException{\r
-               XMLElementParser parser = element.getParser();\r
+       private void handleElement(Deque<ParserElement> parents, ParserElement element) throws SAXException{\r
+               XMLElementParser parser = element.getElementParser();\r
                if (parser != null) {\r
                        try {\r
                                parser.configure(graph, parents, element);\r
                                if (parents.size() > 0) {\r
-                                       Element parent = parents.peek();\r
-                                       if (parent.getParser() != null) {\r
-                                               if (!parent.getParser().connectChild(graph, parent, element))\r
+                                       ParserElement parent = parents.peek();\r
+                                       if (parent.getElementParser() != null) {\r
+                                               if (!parent.getElementParser().connectChild(graph, parent, element))\r
                                                        if (!parser.connectParent(graph, parent, element)) {\r
                                                                String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None");\r
                                                                logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
@@ -125,10 +165,10 @@ public class XMLParser extends DefaultHandler implements Serializable {
                                }\r
                                String id = parser.getID();\r
                                if (id != null) {\r
-                                       Element existing = idMap.put(id, element);\r
+                                       ParserElement existing = idMap.put(id, element);\r
                                        if (existing != null) {\r
                                                // report error + use id priorities to select the kept element.\r
-                                               boolean useExt = existing.parser.idPriority() > element.parser.idPriority();\r
+                                               boolean useExt = existing.elementParser.idPriority() > element.elementParser.idPriority();\r
                                                if (useExt)\r
                                                        idMap.put(id, existing);\r
                                                String err = "Duplicate XML element id: " + id + " for " + element.getQName() + " and " + existing.getQName() + ", using " + (useExt ? existing.getQName() : element.getQName());\r
@@ -140,9 +180,9 @@ public class XMLParser extends DefaultHandler implements Serializable {
                                throw new SAXException(e);\r
                        }\r
                } else {\r
-                       Element parent = parents.peek();\r
+                       ParserElement parent = parents.peek();\r
                        if (parent != null) { \r
-                               parser = parent.getParser();\r
+                               parser = parent.getElementParser();\r
                                if (parser != null && parser instanceof UnrecognizedElementParser) {\r
                                        try {\r
                                                ((UnrecognizedElementParser)parser).configureChild(graph, parents, parent, element);\r
@@ -154,8 +194,8 @@ public class XMLParser extends DefaultHandler implements Serializable {
                }\r
        }\r
        \r
-       private void handleCharacters(Element element, String string) throws SAXException{\r
-               XMLElementParser parser = element.getParser();\r
+       private void handleCharacters(ParserElement element, String string) throws SAXException{\r
+               XMLElementParser parser = element.getElementParser();\r
                if (parser != null) {\r
                        try {\r
                                parser.configure(graph, element, string);\r
@@ -166,11 +206,11 @@ public class XMLParser extends DefaultHandler implements Serializable {
                }\r
        }\r
        \r
-       private static String PLUGIN_ID = "org.simantics.xml.sax.base";\r
+       \r
        \r
        public void done() throws SAXException{\r
                try {\r
-                       for (Element e : idReferenceElements) {\r
+                       for (ParserElement e : idReferenceElements) {\r
                                IDReferenceParser parser = (IDReferenceParser)parsers.get(e.qName);\r
                                if (!parser.connectReferences(graph, e, idMap)) {\r
                                        String err ="Could not resolve ID references for " + e.getQName() + " " + e.getUri();\r
@@ -187,38 +227,46 @@ public class XMLParser extends DefaultHandler implements Serializable {
                return root;\r
        }\r
        \r
+       StringBuilder charactersValue;\r
+       \r
        @Override\r
        public void startElement(String uri, String localName, String name,     Attributes attributes) throws SAXException {\r
-               Element e = new Element(uri,localName,name,attributes);\r
+               ParserElement e = new ParserElement(uri,localName,name,attributes);\r
                \r
                loadElement(current,e);\r
                current.push(e);\r
+               \r
+               charactersValue = new StringBuilder();\r
        }\r
        \r
        @Override\r
        public void endElement(String uri, String localName, String name)\r
                        throws SAXException {\r
-               Element e = null;\r
+               ParserElement e = null;\r
                if (!current.isEmpty()) {\r
                        e = current.pop();\r
                }\r
                if (e != null) {\r
+                       if (charactersValue.length() > 0)\r
+                               handleCharacters(e, charactersValue.toString());\r
                        handleElement(current,e);\r
                }\r
                if (current.isEmpty()) {\r
                        root = e.getData();\r
                }\r
+               \r
+               charactersValue = new StringBuilder();\r
        }\r
        \r
        @Override\r
        public void characters(char[] ch, int start, int length)\r
                        throws SAXException {\r
-               \r
-               if (!current.isEmpty()) {\r
-                       String s = new String(ch,start,length);\r
-                       Element e = current.peek();\r
-                       handleCharacters(e, s);\r
-               }\r
+               charactersValue.append(new String(ch,start,length));\r
+//             if (!current.isEmpty()) {\r
+//                     String s = new String(ch,start,length);\r
+//                     Element e = current.peek();\r
+//                     handleCharacters(e, s);\r
+//             }\r
                \r
        }\r
        \r