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