1 21 22 package nu.xom.converters; 23 24 import nu.xom.Attribute; 25 import nu.xom.Comment; 26 import nu.xom.DocType; 27 import nu.xom.Document; 28 import nu.xom.Element; 29 import nu.xom.Node; 30 import nu.xom.Nodes; 31 import nu.xom.ParentNode; 32 import nu.xom.ProcessingInstruction; 33 import nu.xom.Text; 34 import nu.xom.XMLException; 35 36 import org.w3c.dom.Attr ; 37 import org.w3c.dom.DOMImplementation ; 38 import org.w3c.dom.DocumentFragment ; 39 import org.w3c.dom.DocumentType ; 40 import org.w3c.dom.NamedNodeMap ; 41 import org.w3c.dom.NodeList ; 42 47 48 62 public class DOMConverter { 63 64 65 private DOMConverter() {} 67 68 69 76 private final static String XMLNS_NAMESPACE 77 = "http://www.w3.org/2000/xmlns/"; 78 79 80 96 public static Document convert(org.w3c.dom.Document domDocument) { 97 98 org.w3c.dom.Element domRoot = domDocument.getDocumentElement(); 99 Element xomRoot = convert(domRoot); 100 Document xomDocument = new Document(xomRoot); 101 102 org.w3c.dom.Node current = domDocument.getFirstChild(); 103 104 for (int position = 0; 106 current.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE; 107 position++, current = current.getNextSibling()) { 108 xomDocument.insertChild(convert(current), position); 109 } 110 current = current.getNextSibling(); 112 113 while (current != null) { 115 xomDocument.appendChild(convert(current)); 116 current = current.getNextSibling(); 117 } 118 119 return xomDocument; 120 121 } 122 123 124 142 public static Nodes convert(DocumentFragment fragment) { 143 144 Nodes result = new Nodes(); 145 NodeList children = fragment.getChildNodes(); 146 for (int i = 0; i < children.getLength(); i++) { 147 result.append(convert(children.item(i))); 148 } 149 150 return result; 151 152 } 153 154 155 private static Node convert(org.w3c.dom.Node node) { 156 157 int type = node.getNodeType(); 158 switch (type) { 159 case org.w3c.dom.Node.ELEMENT_NODE: 160 return convert((org.w3c.dom.Element ) node); 161 case org.w3c.dom.Node.COMMENT_NODE: 162 return convert((org.w3c.dom.Comment ) node); 163 case org.w3c.dom.Node.DOCUMENT_TYPE_NODE: 164 return convert((org.w3c.dom.DocumentType ) node); 165 case org.w3c.dom.Node.TEXT_NODE: 166 return convert((org.w3c.dom.Text ) node); 167 case org.w3c.dom.Node.CDATA_SECTION_NODE: 168 return convert((org.w3c.dom.Text ) node); 169 case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE: 170 return convert((org.w3c.dom.ProcessingInstruction ) node); 171 default: 172 throw new XMLException( 173 "Unexpected DOM node type: " + type); 174 } 175 176 } 177 178 179 195 public static Comment convert(org.w3c.dom.Comment comment) { 196 return new Comment(comment.getNodeValue()); 197 } 198 199 216 public static Text convert(org.w3c.dom.Text text) { 217 return new Text(text.getNodeValue()); 218 } 219 220 221 243 public static Attribute convert(Attr attribute) { 244 245 String name = attribute.getName(); 246 String uri = attribute.getNamespaceURI(); 247 if (uri == null) uri = ""; 248 return new Attribute(name, uri, attribute.getNodeValue()); 249 250 } 251 252 253 271 public static ProcessingInstruction convert( 272 org.w3c.dom.ProcessingInstruction pi) { 273 return new ProcessingInstruction( 274 pi.getTarget(), pi.getNodeValue()); 275 } 276 277 278 295 public static DocType convert(org.w3c.dom.DocumentType doctype) { 296 297 DocType result = 298 new DocType( 299 doctype.getName(), 300 doctype.getPublicId(), 301 doctype.getSystemId()); 302 303 return result; 304 305 } 306 307 308 323 public static Element convert(org.w3c.dom.Element element) { 324 325 org.w3c.dom.Node current = element; 326 Element result = makeElement(element); 327 ParentNode parent = result; 328 boolean backtracking = false; 329 while (true) { 330 if (current.hasChildNodes() && !backtracking) { 331 current = current.getFirstChild(); 332 backtracking = false; 333 } 334 else if (current == element) { 335 break; 336 } 337 else if (current.getNextSibling() != null) { 338 current = current.getNextSibling(); 339 backtracking = false; 340 } 341 else { 342 current = current.getParentNode(); 343 backtracking = true; 344 parent = parent.getParent(); 345 continue; 346 } 347 348 int type = current.getNodeType(); 349 if (type == org.w3c.dom.Node.ELEMENT_NODE) { 350 Element child = makeElement((org.w3c.dom.Element ) current); 351 parent.appendChild(child); 352 if (current.hasChildNodes()) parent = child; 353 } 354 else { 355 Node child = convert(current); 356 parent.appendChild(child); 357 } 358 359 } 360 361 return result; 362 363 } 364 365 366 private static Element makeElement(org.w3c.dom.Element element) { 367 368 String namespaceURI = element.getNamespaceURI(); 369 String tagName = element.getTagName(); 370 Element result = new Element(tagName, namespaceURI); 371 372 NamedNodeMap attributes = element.getAttributes(); 374 for (int i = 0; i < attributes.getLength(); i++) { 375 org.w3c.dom.Attr attribute = (org.w3c.dom.Attr ) attributes.item(i); 376 String name = attribute.getName(); 377 String uri = attribute.getNamespaceURI(); 378 String value = attribute.getValue(); 379 if (uri == null) uri = ""; 380 if (uri.equals(XMLNS_NAMESPACE)) { 381 if (name.equals("xmlns")) continue; 382 String prefix = name.substring(name.indexOf(':') + 1); 383 String currentURI = result.getNamespaceURI(prefix); 384 if (!value.equals(currentURI)) { 385 result.addNamespaceDeclaration(prefix, value); 386 } 387 } 388 else { 389 result.addAttribute(new Attribute(name, uri, value)); 390 } 391 } 392 return result; 393 394 } 395 396 397 414 public static org.w3c.dom.Document convert(Document document, 415 DOMImplementation impl) { 416 417 Element root = document.getRootElement(); 418 String rootName = root.getQualifiedName(); 419 String rootNamespace = root.getNamespaceURI(); 420 DocType doctype = document.getDocType(); 421 DocumentType domDOCTYPE = null; 422 if (doctype != null) { 423 domDOCTYPE = impl.createDocumentType(rootName, 424 doctype.getPublicID(), doctype.getSystemID()); 425 } 426 427 org.w3c.dom.Document domDoc 428 = impl.createDocument(rootNamespace, rootName, domDOCTYPE); 429 org.w3c.dom.Element domRoot = domDoc.getDocumentElement(); 430 431 boolean beforeRoot = true; 432 for (int i = 0; i < document.getChildCount(); i++) { 433 Node original = document.getChild(i); 434 if (original instanceof DocType) continue; 436 else if (original instanceof Element) { 437 convert((Element) original, domDoc); 438 beforeRoot = false; 439 } 440 else { 441 org.w3c.dom.Node domNode = convert(original, domDoc); 442 if (beforeRoot) domDoc.insertBefore(domNode, domRoot); 443 else domDoc.appendChild(domNode); 444 } 445 } 446 447 return domDoc; 448 449 } 450 451 452 private static org.w3c.dom.Node convert( 453 Node node, org.w3c.dom.Document document) { 454 455 if (node instanceof Text) { 456 return convert((Text) node, document); 457 } 458 else if (node instanceof Comment) { 459 return convert((Comment) node, document); 460 } 461 else if (node instanceof ProcessingInstruction) { 462 return convert((ProcessingInstruction) node, document); 463 } 464 else { 467 throw new XMLException( 468 "Unexpected node type: " + node.getClass().getName() 469 ); 470 } 471 472 } 473 474 475 private static org.w3c.dom.Comment convert( 476 Comment comment, org.w3c.dom.Document document) { 477 return document.createComment(comment.getValue()); 478 } 479 480 481 private static org.w3c.dom.Text convert( 482 Text text, org.w3c.dom.Document document) { 483 return document.createTextNode(text.getValue()); 484 } 485 486 487 private static org.w3c.dom.ProcessingInstruction convert( 488 ProcessingInstruction pi, org.w3c.dom.Document document) { 489 return document.createProcessingInstruction( 490 pi.getTarget(), pi.getValue()); 491 } 492 493 494 private static org.w3c.dom.Element convert( 495 Element xomElement, org.w3c.dom.Document document) { 496 497 org.w3c.dom.Element domResult = makeElement(xomElement, document); 498 org.w3c.dom.Node domParent = domResult; 499 Node xomCurrent = xomElement; 500 int index = 0; 501 int[] indexes = new int[10]; 502 int top = 0; 503 indexes[0] = 0; 504 boolean end = false; 505 while (true) { 506 507 if (!end && xomCurrent.getChildCount() > 0) { 508 xomCurrent = xomCurrent.getChild(0); 509 index = 0; 510 top++; 511 indexes = grow(indexes, top); 512 indexes[top] = 0; 513 } 514 else { 515 boolean wasEnd = end; 516 end = false; 517 ParentNode xomParent = xomCurrent.getParent(); 518 org.w3c.dom.Node grandparent = domParent.getParentNode(); 519 if (grandparent.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE 520 && xomCurrent instanceof Element) { 521 domParent = grandparent; 522 } 523 if (xomParent.getChildCount() - 1 == index) { 524 xomCurrent = xomParent; 525 top--; 526 if (xomCurrent == xomElement) break; 527 ParentNode tp = xomCurrent.getParent(); 528 if (tp == null) break; 529 index = indexes[top]; 530 end = true; 531 continue; 532 } 533 else { 534 index++; 535 indexes[top] = index; 536 xomCurrent = xomParent.getChild(index); 537 } 538 } 539 540 if (xomCurrent instanceof Element) { 541 Element currentElement = (Element) xomCurrent; 542 org.w3c.dom.Element child = makeElement(currentElement, document); 543 domParent.appendChild(child); 544 domParent = child; 545 } 546 else { 547 org.w3c.dom.Node child = convert(xomCurrent, document); 548 domParent.appendChild(child); 549 } 550 551 } 553 return domResult; 554 555 } 556 557 558 private static int[] grow(int[] indexes, int top) { 559 560 if (top < indexes.length) return indexes; 561 int[] result = new int[indexes.length*2]; 562 System.arraycopy(indexes, 0, result, 0, indexes.length); 563 return result; 564 565 } 566 567 568 private static org.w3c.dom.Element makeElement( 569 Element element, org.w3c.dom.Document document) { 570 571 org.w3c.dom.Element result; 572 String namespace = element.getNamespaceURI(); 573 574 if (element.getParent() instanceof Document) { 575 result = document.getDocumentElement(); 576 } 577 else if (namespace.equals("")) { 578 result = document.createElement( 579 element.getQualifiedName()); 580 } 581 else { 582 result = document.createElementNS( 583 namespace, element.getQualifiedName()); 584 } 585 586 int attributeCount = element.getAttributeCount(); 587 for (int i = 0; i < attributeCount; i++) { 588 Attribute attribute = element.getAttribute(i); 589 String attns = attribute.getNamespaceURI(); 590 Attr attr; 591 if (attns.equals("")) { 592 attr = document.createAttribute(attribute.getLocalName()); 593 result.setAttributeNode(attr); 594 } 595 else { 596 attr = document.createAttributeNS( 597 attns, attribute.getQualifiedName() 598 ); 599 result.setAttributeNodeNS(attr); 600 } 601 attr.setValue(attribute.getValue()); 602 } 603 604 int namespaceCount = element.getNamespaceDeclarationCount(); 605 for (int i = 0; i < namespaceCount; i++) { 606 String additionalPrefix = element.getNamespacePrefix(i); 607 String uri = element.getNamespaceURI(additionalPrefix); 608 609 ParentNode parentNode = element.getParent(); 610 if (parentNode instanceof Element) { 611 Element parentElement = (Element) parentNode; 612 if (uri.equals( 613 parentElement.getNamespaceURI(additionalPrefix))) { 614 continue; 615 } 616 } 617 else if (uri.equals("")) { continue; } 620 621 if ("".equals(additionalPrefix)) { 622 Attr attr = document.createAttributeNS( 623 XMLNS_NAMESPACE, "xmlns" 624 ); 625 result.setAttributeNodeNS(attr); 626 attr.setValue(uri); 627 } 628 else { 629 Attr attr = document.createAttributeNS( 630 XMLNS_NAMESPACE, 631 "xmlns:" + additionalPrefix 632 ); 633 result.setAttributeNodeNS(attr); 634 attr.setValue(uri); 635 } 636 } 637 638 return result; 639 640 } 641 642 643 } 644 | Popular Tags |