1 28 29 package com.caucho.xml2; 30 31 import com.caucho.log.Log; 32 import com.caucho.util.CharBuffer; 33 import com.caucho.util.L10N; 34 35 import org.w3c.dom.*; 36 import org.xml.sax.Attributes ; 37 import org.xml.sax.ContentHandler ; 38 import org.xml.sax.ErrorHandler ; 39 import org.xml.sax.Locator ; 40 import org.xml.sax.SAXException ; 41 import org.xml.sax.SAXParseException ; 42 43 import javax.xml.namespace.QName ; 44 import java.io.IOException ; 45 import java.util.ArrayList ; 46 import java.util.logging.Level ; 47 import java.util.logging.Logger ; 48 49 52 public class DOMBuilder implements XMLWriter, ContentHandler , ErrorHandler { 53 static final Logger log = Log.open(DOMBuilder.class); 54 static final L10N L = new L10N(DOMBuilder.class); 55 static final String XMLNS = XmlParser.XMLNS; 56 57 private QDocument _doc; 58 private Node _top; 59 private Node _node; 60 61 private String _singleText; 62 private CharBuffer _text = new CharBuffer(); 63 64 private boolean _escapeText; 65 private boolean _strictXml; 66 67 private boolean _isCoalescing = true; 69 private boolean _skipWhitespace = false; 71 72 private ArrayList <QName > _prefixNames = new ArrayList <QName >(); 73 private ArrayList <String > _prefixValues = new ArrayList <String >(); 74 75 private Locator _locator; 76 private ExtendedLocator _extLocator; 77 private String _systemId; 78 79 public DOMBuilder() 80 { 81 } 82 83 public void init(Node top) 84 { 85 if (top instanceof QDocument) 86 _doc = (QDocument) top; 87 else 88 _doc = (QDocument) top.getOwnerDocument(); 89 _top = top; 90 _node = top; 91 92 _singleText = null; 93 94 _prefixNames.clear(); 95 _prefixValues.clear(); 96 } 97 98 public void setSystemId(String systemId) 99 { 100 _systemId = systemId; 101 102 if (systemId != null && _top instanceof Document) { 103 Document tdoc = (Document) _top; 104 DocumentType dtd = tdoc.getDoctype(); 105 if (tdoc instanceof QDocument && dtd == null) { 106 dtd = new QDocumentType(null); 107 ((QDocument) tdoc).setDoctype(dtd); 108 } 109 110 if (dtd instanceof QDocumentType && dtd.getSystemId() == null) 111 ((QDocumentType) dtd).setSystemId(systemId); 112 } 113 114 if (_doc != null) 115 _doc.setSystemId(systemId); 116 } 117 118 public String getSystemId() 119 { 120 return _systemId; 121 } 122 123 public void setFilename(String filename) 124 { 125 if (filename != null && _top instanceof QDocument) { 126 _doc.setRootFilename(filename); 127 } 128 } 129 130 133 public void setStrictXML(boolean isStrictXml) 134 { 135 _strictXml = isStrictXml; 136 } 137 138 141 public void setCoalescing(boolean isCoalescing) 142 { 143 _isCoalescing = isCoalescing; 144 } 145 146 149 public void setSkipWhitespace(boolean skipWhitespace) 150 { 151 _skipWhitespace = skipWhitespace; 152 } 153 154 public void setDocumentLocator(Locator loc) 155 { 156 if (_doc == null) { 157 _doc = new QDocument(); 158 _node = _doc; 159 _top = _doc; 160 } 161 162 _locator = loc; 163 164 if (loc instanceof ExtendedLocator) 165 _extLocator = (ExtendedLocator) loc; 166 167 if (_extLocator != null && _doc.getSystemId() == null) 168 _doc.setLocation(_extLocator.getSystemId(), 169 _extLocator.getFilename(), 170 _extLocator.getLineNumber(), 171 _extLocator.getColumnNumber()); 172 } 173 174 public void startPrefixMapping(String prefix, String url) 175 { 176 if (_node == null || _node == _top) 177 _doc.addNamespace(prefix, url); 178 179 if (prefix.equals("")) { 180 _prefixNames.add(new QName (null, "xmlns", XmlParser.XMLNS)); 181 _prefixValues.add(url); 182 } 183 else { 184 _prefixNames.add(new QName ("xmlns", prefix, XmlParser.XMLNS)); 185 _prefixValues.add(url); 186 } 187 } 188 189 public void endPrefixMapping(String prefix) 190 { 191 } 192 193 public Node getNode() 194 { 195 return _top; 196 } 197 198 public void startDocument() 199 { 200 if (_doc == null) { 201 _doc = new QDocument(); 202 _node = _doc; 203 _top = _doc; 204 } 205 } 206 207 public void endDocument() 208 throws SAXException  209 { 210 popText(); 211 } 212 213 public void setLocation(String filename, int line, int column) 214 { 215 } 216 217 public void startElement(String uri, String localName, String qName) 218 throws IOException  219 { 220 popText(); 221 222 Element elt; 223 224 if (uri != null && ! uri.equals("")) 225 elt = _doc.createElementNS(uri, qName); 226 else if (! qName.equals("")) 227 elt = _doc.createElement(qName); 228 else 229 elt = _doc.createElement(localName); 230 231 if (_node == _doc) { 232 if (_doc.getDocumentElement() == null) 233 ((QDocument) _doc).setDocumentElement(elt); 234 } 235 236 _node.appendChild(elt); 237 _node = elt; 238 239 if (_extLocator != null && elt instanceof QElement) { 240 ((QElement) elt).setLocation(_extLocator.getSystemId(), 241 _extLocator.getFilename(), 242 _extLocator.getLineNumber(), 243 _extLocator.getColumnNumber()); 244 } 245 } 246 247 public void startElement(QName name, QAttributes attributes) 248 throws SAXException  249 { 250 popText(); 251 252 QElement elt = (QElement) _doc.createElementByName(name); 253 _node.appendChild(elt); 254 _node = elt; 255 256 if (_node == _doc) { 257 if (_doc.getDocumentElement() == null) 258 ((QDocument) _doc).setDocumentElement(elt); 259 } 260 261 for (int i = 0; i < _prefixNames.size(); i++) { 262 QName attrName = _prefixNames.get(i); 263 String value = _prefixValues.get(i); 264 265 elt.setAttribute(attrName, value); 266 } 267 268 _prefixNames.clear(); 269 _prefixValues.clear(); 270 271 int length = attributes.getLength(); 272 for (int i = 0; i < length; i++) { 273 QName attrName = attributes.getName(i); 274 String value = attributes.getValue(i); 275 276 elt.setAttribute(attrName, value); 277 } 278 279 if (_extLocator != null) { 280 elt.setLocation(_extLocator.getSystemId(), 281 _extLocator.getFilename(), 282 _extLocator.getLineNumber(), 283 _extLocator.getColumnNumber()); 284 } 285 286 QDocumentType dtd = (QDocumentType) _doc.getDoctype(); 287 if (dtd != null) 288 dtd.fillDefaults(elt); 289 } 290 291 public void startElement(String uri, String localName, String qName, 292 Attributes attributes) 293 throws SAXException  294 { 295 popText(); 296 297 Element elt; 298 299 if (uri != null && ! uri.equals("")) 300 elt = _doc.createElementNS(uri, qName); 301 else if (! qName.equals("")) 302 elt = _doc.createElement(qName); 303 else 304 elt = _doc.createElement(localName); 305 306 if (_node == _doc) { 307 if (_doc.getDocumentElement() == null) 308 ((QDocument) _doc).setDocumentElement(elt); 309 else if (_strictXml) 310 throw error(L.l("expected a single top-level element at `{0}'", qName)); 311 } 312 313 _node.appendChild(elt); 314 _node = elt; 315 316 int length = attributes.getLength(); 317 for (int i = 0; i < length; i++) { 318 String attrUri = attributes.getURI(i); 319 String attrQname = attributes.getQName(i); 320 String value = attributes.getValue(i); 321 322 Attr attr; 323 324 if (attrUri != null && ! attrUri.equals("")) 325 attr = _doc.createAttributeNS(attrUri, attrQname); 326 else if (! attrQname.equals("")) 327 attr = _doc.createAttribute(attrQname); 328 else 329 attr = _doc.createAttribute(attributes.getLocalName(i)); 330 331 attr.setNodeValue(value); 332 333 ((Element) _node).setAttributeNode(attr); 334 } 335 336 if (_extLocator != null) 337 ((QElement) elt).setLocation(_extLocator.getSystemId(), 338 _extLocator.getFilename(), 339 _extLocator.getLineNumber(), 340 _extLocator.getColumnNumber()); 341 342 QDocumentType dtd = (QDocumentType) _doc.getDoctype(); 343 if (dtd != null) { 344 dtd.fillDefaults((QElement) elt); 345 } 346 } 347 348 public void dtd(QDocumentType dtd) 349 { 350 ((QDocument) _doc).setDoctype(dtd); 351 352 ((QDocument) _doc).appendChild(dtd); 353 } 354 355 public void attribute(String uri, String localName, String qName, 356 String value) 357 throws IOException  358 { 359 if (_node instanceof Element) { 360 Attr attr = _doc.createAttributeNS(uri, qName); 361 attr.setNodeValue(value); 362 363 ((Element) _node).setAttributeNode(attr); 364 } 365 else 366 ((QDocument) _node).setAttribute(qName, value); 367 } 368 369 public void endElement(String uri, String localName, String qName) 370 { 371 popText(); 372 373 if (_node != null) _node = _node.getParentNode(); 375 if (_node == null) 376 _node = _doc; 377 } 378 379 public void processingInstruction(String name, String data) 380 { 381 popText(); 382 383 ProcessingInstruction pi = _doc.createProcessingInstruction(name, data); 384 385 _node.appendChild(pi); 386 } 387 388 393 public void comment(char []buf, int offset, int length) 394 throws SAXException  395 { 396 try { 397 comment(new String (buf, offset, length)); 398 } catch (IOException e) { 399 throw new SAXException (e); 400 } 401 } 402 403 408 public void comment(String data) 409 throws IOException  410 { 411 popText(); 412 413 Comment comment = _doc.createComment(data); 414 415 _node.appendChild(comment); 416 } 417 418 public boolean getEscapeText() 419 { 420 return _escapeText; 421 } 422 423 public void setEscapeText(boolean isEscaped) 424 { 425 _escapeText = isEscaped; 426 } 427 428 public void text(String text) 429 throws IOException  430 { 431 if (_singleText == null && _text.length() == 0) { 432 if (! text.equals("")) 433 _singleText = text; 434 } 435 else if (_singleText != null) { 436 _text.append(_singleText); 437 _text.append(text); 438 } 439 else 440 _text.append(text); 441 442 if (! _isCoalescing) 443 popText(); 444 } 445 446 public void text(char []buffer, int offset, int length) 447 throws IOException  448 { 449 if (length == 0) 450 return; 451 452 if (_singleText != null) { 453 _singleText = null; 454 _text.append(_singleText); 455 } 456 _text.append(buffer, offset, length); 457 458 if (! _isCoalescing) 459 popText(); 460 } 461 462 465 public void characters(char []buffer, int offset, int length) 466 throws SAXException  467 { 468 if (length == 0) 469 return; 470 471 if (_strictXml && _node == _doc) { 472 if (_doc.getDocumentElement() == null) { 473 while (length > 0 && XmlChar.isWhitespace(buffer[offset])) { 474 offset++; 475 length--; 476 } 477 478 for (int i = 0; i < length; i++) { 479 if (buffer[offset + i] == '\n' || buffer[offset + i] == '\r') { 480 length = i; 481 break; 482 } 483 } 484 485 if (length > 16) 486 length = 16; 487 488 if (length > 0) 489 throw error(L.l("expected top element at `{0}'", 490 new String (buffer, offset, length))); 491 } 492 } 493 494 _text.append(buffer, offset, length); 495 496 500 } 501 502 509 public void ignorableWhitespace(char []buffer, int offset, int length) 510 throws SAXException  511 { 512 if (! _skipWhitespace) 513 characters(buffer, offset, length); 514 } 515 516 public void entityReference(String name) 517 { 518 popText(); 519 520 QEntityReference er = new QEntityReference(name); 521 er._owner = (QDocument) _doc; 522 523 _node.appendChild(er); 524 } 525 526 public void skippedEntity(String s) 527 { 528 _text.append(s); 529 } 530 531 public void cdata(String text) 532 throws IOException  533 { 534 popText(); 535 536 _node.appendChild(_doc.createCDATASection(text)); 537 } 538 539 public void cdata(char []buffer, int offset, int length) 540 throws IOException  541 { 542 cdata(new String (buffer, offset, length)); 543 } 544 545 private void popText() 546 { 547 if (_singleText != null) { 548 Node text = _doc.createTextNode(_singleText); 549 _node.appendChild(text); 550 551 _singleText = null; 552 return; 553 } 554 555 if (_text.length() == 0) 556 return; 557 558 Node text = _doc.createTextNode(_text.toString()); 559 _text.clear(); 560 561 _node.appendChild(text); 562 } 563 564 public void fatalError(SAXParseException e) 565 throws SAXException  566 { 567 log.log(Level.FINE, e.toString(), e); 568 569 throw error(e.getMessage()); 570 } 571 572 public void error(SAXParseException e) 573 throws SAXException  574 { 575 log.log(Level.FINER, e.toString(), e); 576 577 throw error(e.getMessage()); 578 } 579 580 public void warning(SAXParseException e) 581 throws SAXException  582 { 583 log.log(Level.FINER, e.toString(), e); 584 } 585 586 589 public SAXException createError(Exception e) 590 { 591 if (e instanceof SAXException ) 592 return (SAXException ) e; 593 else 594 return new SAXException (e); 595 } 596 597 600 XmlParseException error(String text) 601 { 602 if (_extLocator != null) 603 return new XmlParseException(_extLocator.getFilename() + ":" + 604 _extLocator.getLineNumber() + ": " + text); 605 else if (_locator != null) 606 return new XmlParseException(_locator.getSystemId() + ":" + 607 _locator.getLineNumber() + ": " + text); 608 else 609 return new XmlParseException(text); 610 } 611 } 612 | Popular Tags |