1 /* Copyright 2002-2006, 2009, 2014 Elliotte Rusty Harold 2 3 This library is free software; you can redistribute it and/or modify 4 it under the terms of version 2.1 of the GNU Lesser General Public 5 License as published by the Free Software Foundation. 6 7 This library is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU Lesser General Public License for more details. 11 12 You should have received a copy of the GNU Lesser General Public 13 License along with this library; if not, write to the 14 Free Software Foundation, Inc., 59 Temple Place, Suite 330, 15 Boston, MA 02111-1307 USA 16 17 You can contact Elliotte Rusty Harold by sending e-mail to 18 elharo@ibiblio.org. Please include the word "XOM" in the 19 subject line. The XOM home page is located at http://www.xom.nu/ 20 */ 21 22 23 package nu.xom; 24 25 import org.xml.sax.SAXException; 26 27 /** 28 * @author Elliotte Rusty Harold 29 * @version 1.2.11 30 * 31 */ 32 class NonVerifyingHandler extends XOMHandler { 33 NonVerifyingHandler(NodeFactory factory)34 NonVerifyingHandler(NodeFactory factory) { 35 super(factory); 36 } 37 38 startElement(String namespaceURI, String localName, String qualifiedName, org.xml.sax.Attributes attributes)39 public void startElement(String namespaceURI, String localName, 40 String qualifiedName, org.xml.sax.Attributes attributes) throws SAXException { 41 42 flushText(); 43 Element element = Element.build(qualifiedName, namespaceURI, localName); 44 if (parent == document) { // root 45 document.setRootElement(element); 46 inProlog = false; 47 } 48 49 current = element; 50 // Need to push this, even if it's null 51 parents.add(element); 52 53 if (parent != document) { 54 // a.k.a. parent not instanceof Document 55 parent.fastInsertChild(element, parent.getChildCount()); 56 } 57 // This is optimized for the very common case where 58 // everything in the document has the same actual base URI. 59 // It may add redundant base URIs in cases like XInclude 60 // where different parts of the document have different 61 // base URIs. 62 String baseURI = locator.getSystemId(); 63 if (baseURI != null && !baseURI.equals(documentBaseURI)) { 64 element.setActualBaseURI(baseURI); 65 } 66 67 // Attach the attributes; this must be done before the 68 // namespaces are attached. 69 int length = attributes.getLength(); 70 71 // We've got a pretty good guess at how many attributes there 72 // will be here; we could ensureCapacity up to that length. 73 // However, that might waste memory because we wouldn't use 74 // the ones for namespace declarations. We could always 75 // trimToSize when we're done, but it's probably not worth 76 // the effort. 77 for (int i = 0; i < length; i++) { 78 String qName = attributes.getQName(i); 79 if (qName.startsWith("xmlns:") || qName.equals("xmlns")) { 80 continue; 81 } 82 else { 83 String namespace = attributes.getURI(i); 84 String value = attributes.getValue(i); 85 Attribute attribute = Attribute.build( 86 qName, 87 namespace, 88 value, 89 convertStringToType(attributes.getType(i)), 90 attributes.getLocalName(i) 91 ); 92 element.fastAddAttribute(attribute); 93 } 94 } 95 96 // Attach the namespaces 97 for (int i = 0; i < length; i++) { 98 String qName = attributes.getQName(i); 99 if (qName.startsWith("xmlns:")) { 100 String namespaceName = attributes.getValue(i); 101 String namespacePrefix = qName.substring(6); 102 String currentValue 103 = element.getNamespaceURI(namespacePrefix); 104 if (!namespaceName.equals(currentValue)) { 105 element.addNamespaceDeclaration( 106 namespacePrefix, namespaceName); 107 } 108 } 109 else if (qName.equals("xmlns")) { 110 String namespaceName = attributes.getValue(i); 111 String namespacePrefix = ""; 112 String currentValue 113 = element.getNamespaceURI(namespacePrefix); 114 if (!namespaceName.equals(currentValue)) { 115 element.addNamespaceDeclaration(namespacePrefix, 116 namespaceName); 117 } 118 } 119 } 120 121 // this is the new parent 122 parent = element; 123 } 124 125 endElement( String namespaceURI, String localName, String qualifiedName)126 public void endElement( 127 String namespaceURI, String localName, String qualifiedName) { 128 129 // If we're immediately inside a skipped element 130 // we need to reset current to null, not to the parent 131 current = (ParentNode) parents.remove(parents.size()-1); 132 flushText(); 133 134 parent = current.getParent(); 135 136 if (parent.isDocument()) { // root element 137 Document doc = (Document) parent; 138 doc.setRootElement((Element) current); 139 } 140 141 } 142 143 144 // accumulate all text that's in the buffer into a text node flushText()145 private void flushText() { 146 147 if (buffer != null) { 148 textString = buffer.toString(); 149 buffer = null; 150 } 151 152 if (textString != null) { 153 Text result; 154 if (!inCDATA) { 155 result = Text.build(textString); 156 } 157 else { 158 result = CDATASection.build(textString); 159 } 160 parent.fastInsertChild(result, parent.getChildCount()); 161 textString = null; 162 } 163 inCDATA = false; 164 finishedCDATA = false; 165 166 } 167 168 processingInstruction(String target, String data)169 public void processingInstruction(String target, String data) throws SAXException { 170 171 // simplify logic???? into two cases in and not in DTD 172 // ditto for comment() method and superclass 173 if (!inDTD) flushText(); 174 else if (!inInternalSubset()) return; 175 176 ProcessingInstruction result = ProcessingInstruction.build(target, data); 177 178 if (!inDTD) { 179 if (inProlog) { 180 parent.fastInsertChild(result, position); 181 position++; 182 } 183 else { 184 parent.fastInsertChild(result, parent.getChildCount()); 185 } 186 } 187 else { 188 internalDTDSubset.append(" "); 189 internalDTDSubset.append(result.toXML()); 190 internalDTDSubset.append("\n"); 191 } 192 193 } 194 195 196 // LexicalHandler events startDTD(String rootName, String publicID, String systemID)197 public void startDTD(String rootName, String publicID, 198 String systemID) { 199 200 inDTD = true; 201 DocType doctype = DocType.build(rootName, publicID, systemID); 202 document.fastInsertChild(doctype, position); 203 position++; 204 internalDTDSubset = new StringBuffer(); 205 this.doctype = doctype; 206 207 } 208 209 comment(char[] text, int start, int length)210 public void comment(char[] text, int start, int length) throws SAXException { 211 212 if (!inDTD) flushText(); 213 else if (!inInternalSubset()) return; 214 215 Comment result = Comment.build(new String(text, start, length)); 216 217 if (!inDTD) { 218 if (inProlog) { 219 parent.insertChild(result, position); 220 position++; 221 } 222 else { 223 parent.fastInsertChild(result, parent.getChildCount()); 224 } 225 } 226 else { 227 internalDTDSubset.append(" "); 228 internalDTDSubset.append(result.toXML()); 229 internalDTDSubset.append("\n"); 230 } 231 232 } 233 234 endDTD()235 public void endDTD() { 236 237 inDTD = false; 238 if (doctype != null) { 239 doctype.fastSetInternalDTDSubset(internalDTDSubset.toString()); 240 } 241 242 } 243 244 245 }