diff options
Diffstat (limited to 'libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java')
-rw-r--r-- | libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java | 182 |
1 files changed, 104 insertions, 78 deletions
diff --git a/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java b/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java index a850460b1e2..aad5ac76e70 100644 --- a/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java +++ b/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java @@ -37,6 +37,7 @@ exception statement from your version. */ package gnu.xml.dom.ls; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -45,20 +46,26 @@ import org.w3c.dom.Attr; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; import org.w3c.dom.Entity; +import org.w3c.dom.EntityReference; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.Text; import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; import org.xml.sax.ext.Attributes2; import org.xml.sax.ext.DeclHandler; import org.xml.sax.ext.LexicalHandler; -import gnu.xml.aelfred2.ContentHandler2; +import org.xml.sax.ext.Locator2; import gnu.xml.dom.DomAttr; import gnu.xml.dom.DomDocument; import gnu.xml.dom.DomDoctype; +import gnu.xml.dom.DomNode; /** * A SAX content and lexical handler used to construct a DOM document. @@ -66,17 +73,28 @@ import gnu.xml.dom.DomDoctype; * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> */ class SAXEventSink - implements ContentHandler2, LexicalHandler, DTDHandler, DeclHandler + implements ContentHandler, LexicalHandler, DTDHandler, DeclHandler { private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE; + private static final HashSet PREDEFINED_ENTITIES = new HashSet(); + static + { + PREDEFINED_ENTITIES.add("amp"); + PREDEFINED_ENTITIES.add("lt"); + PREDEFINED_ENTITIES.add("gt"); + PREDEFINED_ENTITIES.add("quot"); + PREDEFINED_ENTITIES.add("apos"); + } boolean namespaceAware; boolean ignoreWhitespace; boolean expandEntityReferences; boolean ignoreComments; boolean coalescing; + + XMLReader reader; // reference back to the parser to get features DomDocument doc; // document being constructed Node ctx; // current context (parent node) @@ -110,20 +128,42 @@ class SAXEventSink doc.setStrictErrorChecking(false); doc.setBuilding(true); ctx = doc; - } - public void xmlDecl(String version, String encoding, boolean standalone, - String inputEncoding) - throws SAXException - { - if (interrupted) + final String FEATURES = "http://xml.org/sax/features/"; + final String PROPERTIES = "http://xml.org/sax/properties/"; + final String GNU_PROPERTIES = "http://gnu.org/sax/properties/"; + + boolean standalone = reader.getFeature(FEATURES + "is-standalone"); + doc.setXmlStandalone(standalone); + try + { + String version = (String) reader.getProperty(PROPERTIES + + "document-xml-version"); + doc.setXmlVersion(version); + } + catch (SAXNotRecognizedException e) + { + } + catch (SAXNotSupportedException e) + { + } + if (locator != null && locator instanceof Locator2) + { + String encoding = ((Locator2) locator).getEncoding(); + doc.setInputEncoding(encoding); + } + try + { + String encoding = (String) reader.getProperty(GNU_PROPERTIES + + "document-xml-encoding"); + doc.setXmlEncoding(encoding); + } + catch (SAXNotRecognizedException e) + { + } + catch (SAXNotSupportedException e) { - return; } - doc.setXmlVersion(version); - doc.setXmlEncoding(encoding); - doc.setXmlStandalone(standalone); - doc.setInputEncoding(inputEncoding); } public void endDocument() @@ -265,7 +305,7 @@ class SAXEventSink public void characters(char[] c, int off, int len) throws SAXException { - if (interrupted) + if (interrupted || len < 1) { return; } @@ -301,11 +341,8 @@ class SAXEventSink { return; } - if (!inDTD) - { - Node pi = createProcessingInstruction(target, data); - ctx.appendChild(pi); - } + Node pi = createProcessingInstruction(target, data); + ctx.appendChild(pi); } protected Node createProcessingInstruction(String target, String data) @@ -354,6 +391,8 @@ class SAXEventSink public void startEntity(String name) throws SAXException { + if (interrupted) + return; DocumentType doctype = doc.getDoctype(); if (doctype == null) { @@ -361,19 +400,9 @@ class SAXEventSink "reference to entity in undeclared doctype"); } if ("[dtd]".equals(name) || name.charAt(0) == '%') - { - // Ignore DTD and parameter entities - ctx = doctype; - return; - } - if ("lt".equals(name) || - "gt".equals(name) || - "amp".equals(name) || - "apos".equals(name) || - "quot".equals(name)) - { - return; - } + return; + if (PREDEFINED_ENTITIES.contains(name)) + return; // Get entity NamedNodeMap entities = doctype.getEntities(); Entity entity = (Entity) entities.getNamedItem(name); @@ -382,59 +411,47 @@ class SAXEventSink throw new SAXException("SAX parser error: " + "reference to undeclared entity: " + name); } - pushEntity(entity); + EntityReference ref = doc.createEntityReference(name); + // DomDocument populates with the entity replacement text, remove this + Node child = ref.getFirstChild(); + while (child != null) + { + Node nextChild = child.getNextSibling(); + ref.removeChild(child); + child = nextChild; + } + ctx.appendChild(ref); + ctx = ref; } public void endEntity(String name) throws SAXException { + if (interrupted) + return; if ("[dtd]".equals(name) || name.charAt(0) == '%') - { - // Ignore DTD and parameter entities - return; - } - if ("lt".equals(name) || - "gt".equals(name) || - "amp".equals(name) || - "apos".equals(name) || - "quot".equals(name)) - { - return; - } - // Get entity - Entity entity = popEntity(); - // TODO resolve external entities to ensure that entity has content + return; + if (PREDEFINED_ENTITIES.contains(name)) + return; + // Get entity reference + EntityReference ref = (EntityReference) ctx; + if (!ref.getNodeName().equals(name)) + throw new SAXException("expecting end of "+ref.getNodeName()+" entity"); + ctx = ctx.getParentNode(); + if (ref instanceof DomNode) + ((DomNode) ref).makeReadonly(); if (expandEntityReferences) { - // Get entity content - for (Node child = entity.getFirstChild(); child != null; - child = child.getNextSibling()) + // Move entity content from reference node onto context + Node child = ref.getFirstChild(); + while (child != null) { + Node nextChild = child.getNextSibling(); ctx.appendChild(child); + child = nextChild; } + ctx.removeChild(ref); } - else - { - Node entityReference = doc.createEntityReference(name); - ctx.appendChild(entityReference); - } - } - - void pushEntity(Node entity) - { - if (entityCtx == null) - { - entityCtx = new LinkedList(); - } - entityCtx.addLast(ctx); - ctx = entity; - } - - Entity popEntity() - { - Entity ret = (Entity) ctx; - ctx = (Node) entityCtx.removeLast(); - return ret; } public void startCDATA() @@ -456,11 +473,8 @@ class SAXEventSink { return; } - if (!inDTD) - { - Node comment = createComment(c, off, len); - ctx.appendChild(comment); - } + Node comment = createComment(c, off, len); + ctx.appendChild(comment); } protected Node createComment(char[] c, int off, int len) @@ -477,6 +491,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("notation decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; doctype.declareNotation(name, publicId, systemId); } @@ -489,6 +505,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("unparsed entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, publicId, systemId, notationName); @@ -503,6 +521,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("element decl outside DTD"); // Ignore fake element declarations generated by ValidationConsumer. // If an element is not really declared in the DTD it will not be // declared in the document model. @@ -522,6 +542,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("attribute decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; doctype.attributeDecl(eName, aName, type, mode, value); } @@ -533,6 +555,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("internal entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, null, null, null); if (entity != null) @@ -549,6 +573,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("external entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, publicId, systemId, null); } |