1 19 20 package org.netbeans.modules.schema2beans; 21 22 import java.io.*; 23 import org.w3c.dom.*; 24 import org.xml.sax.*; 25 26 public class XMLUtil { 27 private XMLUtil() {} 28 29 33 public static void printXML(StringBuffer out, String msg) { 34 printXML(out, msg, true); 35 } 36 37 public static void printXML(StringBuffer out, String msg, boolean attribute) { 38 if (msg == null) return; 39 appendLine(out, msg, attribute); 40 } 41 42 44 public static void printXML(StringBuffer out, char msg, boolean attribute) { 45 if (msg == '&') 46 out.append("&"); 47 else if (msg == '<') 48 out.append("<"); 49 else if (msg == '>') 50 out.append(">"); 51 else if (attribute) { 52 if (msg == '"') 53 out.append("""); 54 else if (msg == '\'') 55 out.append("'"); 56 else if (msg == '\n') 57 out.append("
"); 58 else if (msg == '\t') 59 out.append("	"); 60 else 61 out.append(msg); 62 } else 63 out.append(msg); 64 } 65 66 70 public static void writeXML(java.io.Writer out, String msg) throws java.io.IOException { 71 writeXML(out, msg, true); 72 } 73 74 public static void writeXML(java.io.Writer out, String msg, boolean attribute) throws java.io.IOException { 75 if (msg == null) return; 76 appendLine(out,msg,attribute); 77 } 78 79 81 public static void writeXML(java.io.Writer out, char msg, boolean attribute) throws java.io.IOException { 82 if (msg == '&') 83 out.write("&"); 84 else if (msg == '<') 85 out.write("<"); 86 else if (msg == '>') 87 out.write(">"); 88 else if (attribute) { 89 if (msg == '"') 90 out.write("""); 91 else if (msg == '\'') 92 out.write("'"); 93 else if (msg == '\n') 94 out.write("
"); 95 else if (msg == '\t') 96 out.write("	"); 97 else 98 out.write(msg); 99 } else 100 out.write(msg); 101 } 102 103 public static boolean shouldEscape(char c) { 104 if (c == '&') 105 return true; 106 else if (c == '<') 107 return true; 108 else if (c == '>') 109 return true; 110 return false; 111 } 112 113 public static boolean shouldEscape(String s) { 114 if (s == null) 115 return false; 116 int msgLength = s.length(); 117 for (int i = 0; i < msgLength; ++i) { 118 char c = s.charAt(i); 119 if (shouldEscape(c)) 120 return true; 121 } 122 return false; 123 } 124 125 129 public static void printXML(java.io.Writer out, String msg) throws java.io.IOException { 130 printXML(out, msg, true); 131 } 132 133 public static void printXML(java.io.Writer out, String msg, boolean attribute) throws java.io.IOException { 134 if (msg == null) return; 135 appendLine(out,msg,attribute); 136 } 137 138 private static void appendLine(StringBuffer out, String msg, boolean attribute) { 139 out.append(convertChars(msg,attribute)); 140 } 141 142 private static void appendLine(java.io.Writer out, String msg, boolean attribute) throws java.io.IOException { 143 out.write(convertChars(msg,attribute)); 144 } 145 146 private static String convertChars(String msg, boolean attribute) { 147 String result=msg; 148 if (msg.indexOf("&")>=0) result = result.replaceAll("&","&"); if (msg.indexOf("<")>=0) result = result.replaceAll("<","<"); if (msg.indexOf(">")>=0) result = result.replaceAll(">",">"); if (attribute) { if (msg.indexOf("\"")>=0) result = result.replaceAll("\"","""); if (msg.indexOf("'")>=0) result = result.replaceAll("'","'"); if (msg.indexOf("\n")>=0) result = result.replaceAll("\n","
"); if (msg.indexOf("\t")>=0) result = result.replaceAll("\t","	"); } 164 return result; 165 } 166 167 169 public static void printXML(java.io.Writer out, char msg, boolean attribute) throws java.io.IOException { 170 if (msg == '&') 171 out.write("&"); 172 else if (msg == '<') 173 out.write("<"); 174 else if (msg == '>') 175 out.write(">"); 176 else if (attribute) { 177 if (msg == '"') 178 out.write("""); 179 else if (msg == '\'') 180 out.write("'"); 181 else if (msg == '\n') 182 out.write("
"); 183 else if (msg == '\t') 184 out.write("	"); 185 else 186 out.write(msg); 187 } 188 else 189 out.write(msg); 190 } 191 192 public static class DOMWriter { 193 private java.io.Writer out; 194 private boolean writeCData = false; 195 private String docTypePublic; 196 private String docTypeSystem; 197 198 public DOMWriter() { 199 } 200 201 public void setWriter(java.io.Writer out) { 202 this.out = out; 203 } 204 205 public void setWriteCData(boolean value) { 206 writeCData = value; 207 } 208 209 public void setDocTypePublic(String value) { 210 docTypePublic = value; 211 } 212 213 public void setDocTypeSystem(String value) { 214 docTypeSystem = value; 215 } 216 217 221 public void write(File f, Document document) throws java.io.IOException { 222 OutputStream fout = new FileOutputStream(f); 223 try { 224 write(fout, document); 225 } finally { 226 fout.close(); 227 } 228 } 229 230 234 public void write(OutputStream os, Document document) throws java.io.IOException { 235 write(os, null, document); 236 } 237 238 243 public void write(OutputStream os, String encoding, Document document) throws java.io.IOException { 244 if (encoding == null) 245 encoding = "UTF-8"; 246 out = new BufferedWriter(new OutputStreamWriter(os, encoding)); 247 write(document, encoding); 248 } 249 250 253 public void write(Document document) throws java.io.IOException { 254 write(document, null); 255 } 256 257 261 public void write(Document document, String encoding) throws java.io.IOException { 262 write(document, encoding, true); 263 } 264 265 271 public void write(Document document, String encoding, 272 boolean writeHeader) throws java.io.IOException { 273 if (writeHeader) { 274 out.write("<?xml version=\"1.0\""); if (encoding != null) { 276 out.write(" encoding=\""+encoding+"\"?>\n"); } else 278 out.write(" encoding=\"UTF-8\"?>\n"); } 280 if (docTypePublic != null || docTypeSystem != null) { 281 String docName = getDocTypeName(document); 282 DocumentType docType = document.getDoctype(); 283 NamedNodeMap entities = null; 284 if (docType != null) 285 entities = docType.getEntities(); 286 write(docName, docTypePublic, docTypeSystem, entities); 287 out.write("\n"); 288 } 289 NodeList children = document.getChildNodes(); 290 int length = children.getLength(); 291 for (int i = 0; i < length; ++i) { 293 Node node = children.item(i); 294 if (node instanceof DocumentType) { 295 write(node); 296 out.write("\n"); 297 } 298 } 299 for (int i = 0; i < length; ++i) { 301 Node node = children.item(i); 302 if (!(node instanceof DocumentType)) { 303 write(node); 304 out.write("\n"); 305 } 306 } 307 308 out.flush(); 309 } 310 311 public void write(Node node) throws java.io.IOException { 312 boolean needsReturnBetweenChildren = false; 313 314 NodeList children = node.getChildNodes(); 315 if (node instanceof Element) { 316 out.write("<"+node.getNodeName()); 317 write(node.getAttributes()); 318 if (children.getLength() == 0 || 319 (children.getLength() == 1 && 320 children.item(0) instanceof Text && 321 "".equals(children.item(0).getNodeValue()) )) { 322 out.write("/>"); 323 return; 324 } 325 out.write(">"); 326 } else if (node instanceof Text) { 327 printXML(node.getNodeValue(), false); 328 } else if (node instanceof Document) { 329 needsReturnBetweenChildren = true; 330 } else if (node instanceof DocumentType) { 331 write((DocumentType) node); 332 } else if (node instanceof Comment) { 333 write((Comment) node); 334 } else if (node instanceof Entity) { 335 write((Entity) node); 336 } else if (node instanceof ProcessingInstruction) { 337 write((ProcessingInstruction) node); 338 } else { 339 System.err.println("! schema2beans found unknown node type in DOM graph:"); 340 System.err.println("write: node.getClass="+node.getClass()+" node="+node); 341 System.err.println("write: nodename="+node.getNodeName()+" nodevalue="+node.getNodeValue()); 342 System.err.println("write: getAttributes="+node.getAttributes()); 343 } 344 345 int length = children.getLength(); 346 for (int i = 0; i < length; ++i) { 347 write(children.item(i)); 348 if (needsReturnBetweenChildren) 349 out.write("\n"); 350 } 351 if (node instanceof Element) { 352 out.write("</"+node.getNodeName()+">"); 353 } 354 } 355 356 protected void write(DocumentType docType) throws java.io.IOException { 357 if (docTypePublic != null || docTypeSystem != null) { 359 return; 361 } 362 write(docType.getName(), docType.getPublicId(), 363 docType.getSystemId(), docType.getEntities()); 364 } 365 366 protected void write(String docName, String publicId, 367 String systemId, NamedNodeMap entities) throws java.io.IOException { 368 out.write("<!DOCTYPE "+docName); if (publicId != null) { 370 out.write(" PUBLIC \""); XMLUtil.printXML(out, publicId); 372 out.write("\""); if (systemId == null) 374 systemId = "SYSTEM"; } 376 if (systemId != null) { 377 out.write(" \""); XMLUtil.printXML(out, systemId); 379 out.write("\""); } 381 if (entities != null) { 382 int length = entities.getLength(); 383 if (length > 0) { 384 out.write(" ["); for (int i = 0; i < length; ++i) { 386 Node node = entities.item(i); 387 write(node); 388 } 389 out.write("]"); } 391 } 392 out.write(">"); } 394 395 protected void write(Comment comment) throws java.io.IOException { 396 out.write("<!--"); 398 String text = comment.getNodeValue(); 399 int pos = text.indexOf("--"); 401 while (pos >= 0) { 402 out.write(text.substring(0, pos)); 403 out.write("--"); 404 text = text.substring(pos+2, text.length()); 405 pos = text.indexOf("--"); 406 } 407 out.write(text); 408 out.write("-->"); 409 } 410 411 protected void write(Entity entity) throws java.io.IOException { 412 out.write("<!ENTITY "+entity.getNodeName()); 413 427 out.write(" UNKNOWN>"); 428 } 429 430 protected void write(ProcessingInstruction pi) throws java.io.IOException { 431 if ("xml".equals(pi.getTarget())) { 433 return; 435 } 436 out.write("<?"+pi.getTarget()+" "+pi.getData()+"?>"); 437 } 438 439 442 protected void write(NamedNodeMap nodes) throws java.io.IOException { 443 int length = nodes.getLength(); 444 for (int i = 0; i < length; ++i) { 445 Node node = nodes.item(i); 446 out.write(" "); 447 out.write(node.getNodeName()); 448 out.write("=\""); 449 XMLUtil.printXML(out, node.getNodeValue()); 450 out.write("\""); 451 } 452 } 453 454 protected void printXML(String msg, boolean attribute) throws java.io.IOException { 455 if (writeCData && msg.indexOf("]]>") < 0) { 456 boolean shouldEscape = XMLUtil.shouldEscape(msg); 457 if (shouldEscape) 458 out.write("<![CDATA["); 459 out.write(msg); 460 if (shouldEscape) 461 out.write("]]>"); 462 } else 463 XMLUtil.printXML(out, msg, attribute); 464 } 465 } 466 467 static protected String getDocTypeName(Document doc) { 469 NodeList children = doc.getChildNodes(); 471 int length = children.getLength(); 472 for (int i = 0; i < length; ++i) { 473 Node node = children.item(i); 474 if (node instanceof DocumentType) { 475 DocumentType docType = (DocumentType) node; 476 return docType.getName(); 477 } 478 } 479 Node rootNode = doc.getDocumentElement(); 481 return rootNode.getNodeName(); 482 } 483 484 490 public static void reindent(Document doc, String indent) { 491 reindent(doc, doc, -1, indent); 492 } 493 494 503 public static boolean reindent(Document doc, Node node, 504 int level, String indent) { 505 String nodeValue = node.getNodeValue(); 506 507 boolean hasOnlyWhitespaceTextChildren = true; 508 NodeList children = node.getChildNodes(); 509 int length = children.getLength(); 510 for (int i = 0; i < length; ++i) { 511 if (!reindent(doc, children.item(i), level+1, indent)) 512 hasOnlyWhitespaceTextChildren = false; 513 } 514 515 525 526 if (hasOnlyWhitespaceTextChildren && level >= 0 && length > 0) { 527 530 StringBuffer idealWhitespaceBuf = new StringBuffer (); 531 printLevel(idealWhitespaceBuf, level, indent); 532 String idealFinalWhitespace = "\n" + idealWhitespaceBuf.toString().intern(); 533 printLevel(idealWhitespaceBuf, 1, indent); 534 String idealChildWhitespace = "\n"+idealWhitespaceBuf.toString().intern(); 535 if (length > 1 && !(children.item(length-1) instanceof Text)) { 541 node.appendChild(doc.createTextNode(idealFinalWhitespace)); 543 ++length; 544 } 545 547 boolean shouldBeTextNode = true; Text textNode; 549 for (int i = 0; i < length; ++i) { 550 Node childNode = children.item(i); 551 boolean isTextNode = (childNode instanceof Text); 552 if (shouldBeTextNode) { 554 if (isTextNode) { 555 String childNodeValue = childNode.getNodeValue().intern(); 556 if (length == 1) { 557 continue; 560 } 561 562 textNode = (Text) childNode; 563 if (i == length-1) { 565 if (idealFinalWhitespace != childNodeValue) { 566 if (textNode.getLength() > 0) 568 textNode.deleteData(0, textNode.getLength()); 569 textNode.appendData(idealFinalWhitespace); 570 } 571 572 } else { 573 if (idealChildWhitespace != childNodeValue) { 574 textNode.deleteData(0, textNode.getLength()); 576 textNode.appendData(idealChildWhitespace); 577 } 578 } 579 shouldBeTextNode ^= true; 580 } else { 581 if (i == length-1) { 584 node.insertBefore(doc.createTextNode(idealChildWhitespace), childNode); 586 node.appendChild(doc.createTextNode(idealFinalWhitespace)); 587 ++length; 588 } else { 589 node.insertBefore(doc.createTextNode(idealChildWhitespace), childNode); 591 } 592 ++i; 598 ++length; 599 } 600 } else { 601 if (isTextNode) { 602 node.removeChild(childNode); 606 --i; 607 --length; 608 if (i == length-1 && i >= 0) { 609 childNode = children.item(i); 612 String childNodeValue = childNode.getNodeValue().intern(); 613 if (idealFinalWhitespace != childNodeValue) { 614 textNode = (Text) childNode; 615 if (textNode.getLength() > 0) 617 textNode.deleteData(0, textNode.getLength()); 618 textNode.appendData(idealFinalWhitespace); 619 } 620 } 621 } else { 622 shouldBeTextNode ^= true; 625 } 626 } 627 } 628 } 629 630 if (node instanceof Text) { 633 if (nodeValue == null) 634 return true; 635 return (nodeValue.trim().equals("")); 636 } 637 return true; 638 } 639 640 protected static void printLevel(StringBuffer out, int level, String indent) { 641 for (int i = 0; i < level; ++i) { 642 out.append(indent); 643 } 644 } 645 646 650 public static Locator findLocationXPath(InputSource in, String xpathExpr) throws IOException, org.xml.sax.SAXException { 651 XMLReader parser; 652 try { 653 javax.xml.parsers.SAXParserFactory spf 654 = javax.xml.parsers.SAXParserFactory.newInstance(); 655 spf.setNamespaceAware(true); 656 parser = spf.newSAXParser().getXMLReader(); 657 } catch (javax.xml.parsers.ParserConfigurationException e) { 658 throw new RuntimeException (e); 659 } 660 XPathLocator locator = new XPathLocator(xpathExpr); 661 parser.setContentHandler(locator); 662 parser.parse(in); 663 return locator.getDocumentLocator(); 664 } 665 666 668 public static boolean isAttrContent(int i) { 669 if (i<9) return false; 671 if (i>9 && i<32) return false; 672 return true; 676 } 677 678 private static class XPathLocator 679 extends org.xml.sax.helpers.DefaultHandler implements ContentHandler { 680 private String xpathExpr; 681 private String [] xpathParts; 682 private int partNum; 683 private String desiredElementName; 684 private int desiredPosition; 685 private boolean isAttribute; 686 private Locator locator = null; 687 private Locator resultLocator = null; 688 689 public XPathLocator(String xpathExpr) { 690 xpathExpr = xpathExpr.trim(); 691 if (xpathExpr.startsWith("/")) 692 xpathExpr = xpathExpr.substring(1, xpathExpr.length()); 693 this.xpathExpr = xpathExpr; 694 xpathParts = xpathExpr.split("/"); partNum = 0; 696 setElementName(); 697 } 698 699 private void setElementName() { 700 desiredElementName = xpathParts[partNum].trim(); 701 desiredPosition = 0; 702 isAttribute = false; 703 int startPos = desiredElementName.indexOf('['); 704 int endPos = desiredElementName.indexOf(']'); 705 if (startPos >= 0) { 707 if (endPos < 0) 708 throw new IllegalArgumentException ("XPath subexpression ("+desiredElementName+") is missing an ending ']'."); 709 String subExpr = desiredElementName.substring(startPos+1, 710 endPos).trim(); 711 desiredElementName = desiredElementName.substring(0, startPos); 712 if (subExpr.startsWith("position()=")) { 714 desiredPosition = Integer.parseInt(subExpr.substring(11, subExpr.length())); 715 } else { 716 boolean allDigits = subExpr.length() > 0; 717 for (int i = 0; i < subExpr.length(); ++i) { 718 if (!Character.isDigit(subExpr.charAt(i))) { 719 allDigits = false; 720 break; 721 } 722 } 723 if (allDigits) { 724 desiredPosition = Integer.parseInt(subExpr); 725 } else { 726 throw new UnsupportedOperationException ("XPath ("+subExpr+" in "+xpathExpr+") not supported."); 727 } 728 } 729 } else if (desiredElementName.startsWith("@")) { 730 isAttribute = true; 731 desiredElementName = desiredElementName.substring(1, desiredElementName.length()); 732 } 733 } 735 736 739 private boolean foundGotoNext() { 740 ++partNum; 741 if (partNum >= xpathParts.length) { 742 resultLocator = new org.xml.sax.helpers.LocatorImpl (locator); 744 return true; 745 } else { 746 setElementName(); 748 return false; 749 } 750 } 751 752 public Locator getDocumentLocator() { 753 return resultLocator; 754 } 755 756 public void setDocumentLocator(Locator locator) { 757 this.locator = locator; 758 } 759 760 public void startElement(String namespaceURI, String localName, 761 String rawName, Attributes attrs) throws SAXException { 762 if (resultLocator != null) { 763 return; 765 } 766 if (desiredElementName.equals(localName) || 767 desiredElementName.equals(rawName)) { 768 if (desiredPosition == 0) { 770 if (!foundGotoNext()) { 772 if (isAttribute) { 775 for (int i = 0, size = attrs.getLength(); 777 i < size; ++i) { 778 if (desiredElementName.equals(attrs.getLocalName(i)) || 779 desiredElementName.equals(attrs.getQName(i))) { 780 foundGotoNext(); 782 return; 783 } 784 } 785 } 786 } 787 } else { 788 --desiredPosition; 789 } 790 } 791 } 792 } 793 } 794 | Popular Tags |