1 10 11 package mondrian.tui; 12 13 import org.apache.xerces.dom.DocumentImpl; 14 import org.apache.xerces.impl.Constants; 15 import org.apache.xerces.parsers.DOMParser; 16 import org.apache.xml.serialize.OutputFormat; 17 import org.apache.xml.serialize.XMLSerializer; 18 import org.apache.xpath.domapi.XPathEvaluatorImpl; 19 import org.w3c.dom.*; 20 import org.w3c.dom.xpath.*; 21 import org.xml.sax.*; 22 23 import javax.xml.parsers.*; 24 import javax.xml.transform.*; 25 import javax.xml.transform.dom.DOMResult ; 26 import javax.xml.transform.dom.DOMSource ; 27 import java.io.*; 28 import java.util.*; 29 30 37 public class XmlUtil { 38 39 public static final String LINE_SEP = 40 System.getProperty("line.separator", "\n"); 41 42 43 public static final String SOAP_PREFIX = "SOAP-ENV"; 44 public static final String XSD_PREFIX = "xsd"; 45 46 public static final String XMLNS = "xmlns"; 47 48 public static final String NAMESPACES_FEATURE_ID = 49 "http://xml.org/sax/features/namespaces"; 50 public static final String VALIDATION_FEATURE_ID = 51 "http://xml.org/sax/features/validation"; 52 53 public static final String SCHEMA_VALIDATION_FEATURE_ID = 54 "http://apache.org/xml/features/validation/schema"; 55 public static final String FULL_SCHEMA_VALIDATION_FEATURE_ID = 56 "http://apache.org/xml/features/validation/schema-full-checking"; 57 58 public static final String DEFER_NODE_EXPANSION = 59 "http://apache.org/xml/features/dom/defer-node-expansion"; 60 61 public static final String SCHEMA_LOCATION = 62 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION; 63 64 68 public static final String getSoapXmlaXds2xd(String xmlaPrefix) { 69 return 70 "<?xml version='1.0'?>" + LINE_SEP + 71 "<xsl:stylesheet " + LINE_SEP + 72 "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " + LINE_SEP + 73 "xmlns:xalan='http://xml.apache.org/xslt' " + LINE_SEP + 74 "xmlns:xsd='http://www.w3.org/2001/XMLSchema' " + LINE_SEP + 75 "xmlns:ROW='urn:schemas-microsoft-com:xml-analysis:rowset' " + LINE_SEP + 76 "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " + LINE_SEP + 77 "xmlns:xmla='urn:schemas-microsoft-com:xml-analysis' " + LINE_SEP + 78 "version='1.0' " + LINE_SEP + 79 "> " + LINE_SEP + 80 "<xsl:output method='xml' " + LINE_SEP + 81 "encoding='UTF-8' " + LINE_SEP + 82 "indent='yes' " + LINE_SEP + 83 "xalan:indent-amount='2'/> " + LINE_SEP + 84 " " + LINE_SEP + 85 "<!-- consume '/' and apply --> " + LINE_SEP + 86 "<xsl:template match='/'> " + LINE_SEP + 87 "<xsl:apply-templates/> " + LINE_SEP + 88 "</xsl:template> " + LINE_SEP + 89 "<!-- consume 'Envelope' and apply --> " + LINE_SEP + 90 "<xsl:template match='SOAP-ENV:Envelope'> " + LINE_SEP + 91 "<xsl:apply-templates/> " + LINE_SEP + 92 "</xsl:template> " + LINE_SEP + 93 "<!-- consume 'Header' --> " + LINE_SEP + 94 "<xsl:template match='SOAP-ENV:Header'> " + LINE_SEP + 95 "</xsl:template> " + LINE_SEP + 96 "<!-- consume 'Body' and apply --> " + LINE_SEP + 97 "<xsl:template match='SOAP-ENV:Body'> " + LINE_SEP + 98 "<xsl:apply-templates/> " + LINE_SEP + 99 "</xsl:template> " + LINE_SEP + 100 "<!-- consume 'DiscoverResponse' and apply --> " + LINE_SEP + 101 "<xsl:template match='" + xmlaPrefix + ":DiscoverResponse'> " + LINE_SEP + 102 "<xsl:apply-templates/> " + LINE_SEP + 103 "</xsl:template> " + LINE_SEP + 104 "<!-- consume 'return' and apply --> " + LINE_SEP + 105 "<xsl:template match='" + xmlaPrefix + ":return'> " + LINE_SEP + 106 "<xsl:apply-templates/> " + LINE_SEP + 107 "</xsl:template> " + LINE_SEP + 108 "<!-- consume 'xsd:schema' --> " + LINE_SEP + 109 "<xsl:template match='xsd:schema'> " + LINE_SEP + 110 "</xsl:template> " + LINE_SEP + 111 "<!-- copy everything else --> " + LINE_SEP + 112 "<xsl:template match='*|@*'> " + LINE_SEP + 113 "<xsl:copy> " + LINE_SEP + 114 "<xsl:apply-templates select='@*|node()'/> " + LINE_SEP + 115 "</xsl:copy> " + LINE_SEP + 116 "</xsl:template> " + LINE_SEP + 117 "</xsl:stylesheet>"; 118 } 119 120 124 public static final String getSoapXmlaXds2xs(String xmlaPrefix) { 125 return 126 "<?xml version='1.0'?> " + LINE_SEP + 127 "<xsl:stylesheet " + LINE_SEP + 128 "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " + LINE_SEP + 129 "xmlns:xalan='http://xml.apache.org/xslt' " + LINE_SEP + 130 "xmlns:xsd='http://www.w3.org/2001/XMLSchema' " + LINE_SEP + 131 "xmlns:ROW='urn:schemas-microsoft-com:xml-analysis:rowset' " + LINE_SEP + 132 "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " + LINE_SEP + 133 "xmlns:xmla='urn:schemas-microsoft-com:xml-analysis' " + LINE_SEP + 134 "version='1.0' " + LINE_SEP + 135 "> " + LINE_SEP + 136 "<xsl:output method='xml' " + LINE_SEP + 137 "encoding='UTF-8' " + LINE_SEP + 138 "indent='yes' " + LINE_SEP + 139 "xalan:indent-amount='2'/> " + LINE_SEP + 140 "<!-- consume '/' and apply --> " + LINE_SEP + 141 "<xsl:template match='/'> " + LINE_SEP + 142 "<xsl:apply-templates/> " + LINE_SEP + 143 "</xsl:template> " + LINE_SEP + 144 "<!-- consume 'Envelope' and apply --> " + LINE_SEP + 145 "<xsl:template match='SOAP-ENV:Envelope'> " + LINE_SEP + 146 "<xsl:apply-templates/> " + LINE_SEP + 147 "</xsl:template> " + LINE_SEP + 148 "<!-- consume 'Header' --> " + LINE_SEP + 149 "<xsl:template match='SOAP-ENV:Header'> " + LINE_SEP + 150 "</xsl:template> " + LINE_SEP + 151 "<!-- consume 'Body' and apply --> " + LINE_SEP + 152 "<xsl:template match='SOAP-ENV:Body'> " + LINE_SEP + 153 "<xsl:apply-templates/> " + LINE_SEP + 154 "</xsl:template> " + LINE_SEP + 155 "<!-- consume 'DiscoverResponse' and apply --> " + LINE_SEP + 156 "<xsl:template match='" + xmlaPrefix + ":DiscoverResponse'> " + LINE_SEP + 157 "<xsl:apply-templates/> " + LINE_SEP + 158 "</xsl:template> " + LINE_SEP + 159 "<!-- consume 'return' and apply --> " + LINE_SEP + 160 "<xsl:template match='" + xmlaPrefix + ":return'> " + LINE_SEP + 161 "<xsl:apply-templates/> " + LINE_SEP + 162 "</xsl:template> " + LINE_SEP + 163 "<!-- consume 'root' and apply --> " + LINE_SEP + 164 "<xsl:template match='ROW:root'> " + LINE_SEP + 165 "<xsl:apply-templates/> " + LINE_SEP + 166 "</xsl:template> " + LINE_SEP + 167 "<!-- consume 'row' --> " + LINE_SEP + 168 "<xsl:template match='ROW:row'> " + LINE_SEP + 169 "</xsl:template> " + LINE_SEP + 170 "<!-- copy everything else --> " + LINE_SEP + 171 "<xsl:template match='*|@*'> " + LINE_SEP + 172 "<xsl:copy> " + LINE_SEP + 173 "<xsl:apply-templates select='@*|node()'/> " + LINE_SEP + 174 "</xsl:copy> " + LINE_SEP + 175 "</xsl:template> " + LINE_SEP + 176 "</xsl:stylesheet>"; 177 } 178 179 182 public static final String getXmlaXds2xd(String ns) { 183 String xmlaPrefix = (ns == null) ? "" : (ns + ":"); 184 return 185 "<?xml version='1.0'?>" + LINE_SEP + 186 "<xsl:stylesheet " + LINE_SEP + 187 "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " + LINE_SEP + 188 "xmlns:xalan='http://xml.apache.org/xslt' " + LINE_SEP + 189 "xmlns:xsd='http://www.w3.org/2001/XMLSchema' " + LINE_SEP + 190 "xmlns:ROW='urn:schemas-microsoft-com:xml-analysis:rowset' " + LINE_SEP + 191 "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " + LINE_SEP + 192 "xmlns:xmla='urn:schemas-microsoft-com:xml-analysis' " + LINE_SEP + 193 "version='1.0' " + LINE_SEP + 194 "> " + LINE_SEP + 195 "<xsl:output method='xml' " + LINE_SEP + 196 "encoding='UTF-8' " + LINE_SEP + 197 "indent='yes' " + LINE_SEP + 198 "xalan:indent-amount='2'/> " + LINE_SEP + 199 " " + LINE_SEP + 200 "<!-- consume '/' and apply --> " + LINE_SEP + 201 "<xsl:template match='/'> " + LINE_SEP + 202 "<xsl:apply-templates/> " + LINE_SEP + 203 "</xsl:template> " + LINE_SEP + 204 "<!-- consume 'DiscoverResponse' and apply --> " + LINE_SEP + 205 "<xsl:template match='" + xmlaPrefix + "DiscoverResponse'> " + LINE_SEP + 206 "<xsl:apply-templates/> " + LINE_SEP + 207 "</xsl:template> " + LINE_SEP + 208 "<!-- consume 'return' and apply --> " + LINE_SEP + 209 "<xsl:template match='" + xmlaPrefix + "return'> " + LINE_SEP + 210 "<xsl:apply-templates/> " + LINE_SEP + 211 "</xsl:template> " + LINE_SEP + 212 "<!-- consume 'xsd:schema' --> " + LINE_SEP + 213 "<xsl:template match='xsd:schema'> " + LINE_SEP + 214 "</xsl:template> " + LINE_SEP + 215 "<!-- copy everything else --> " + LINE_SEP + 216 "<xsl:template match='*|@*'> " + LINE_SEP + 217 "<xsl:copy> " + LINE_SEP + 218 "<xsl:apply-templates select='@*|node()'/> " + LINE_SEP + 219 "</xsl:copy> " + LINE_SEP + 220 "</xsl:template> " + LINE_SEP + 221 "</xsl:stylesheet>"; 222 } 223 224 227 public static final String getXmlaXds2xs(String ns) { 228 String xmlaPrefix = (ns == null) ? "" : (ns + ":"); 229 return 230 "<?xml version='1.0'?> " + LINE_SEP + 231 "<xsl:stylesheet " + LINE_SEP + 232 "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " + LINE_SEP + 233 "xmlns:xalan='http://xml.apache.org/xslt' " + LINE_SEP + 234 "xmlns:xsd='http://www.w3.org/2001/XMLSchema' " + LINE_SEP + 235 "xmlns:ROW='urn:schemas-microsoft-com:xml-analysis:rowset' " + LINE_SEP + 236 "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " + LINE_SEP + 237 "xmlns:xmla='urn:schemas-microsoft-com:xml-analysis' " + LINE_SEP + 238 "version='1.0' " + LINE_SEP + 239 "> " + LINE_SEP + 240 "<xsl:output method='xml' " + LINE_SEP + 241 "encoding='UTF-8' " + LINE_SEP + 242 "indent='yes' " + LINE_SEP + 243 "xalan:indent-amount='2'/> " + LINE_SEP + 244 "<!-- consume '/' and apply --> " + LINE_SEP + 245 "<xsl:template match='/'> " + LINE_SEP + 246 "<xsl:apply-templates/> " + LINE_SEP + 247 "</xsl:template> " + LINE_SEP + 248 "<!-- consume 'DiscoverResponse' and apply --> " + LINE_SEP + 249 "<xsl:template match='" + xmlaPrefix + "DiscoverResponse'> " + LINE_SEP + 250 "<xsl:apply-templates/> " + LINE_SEP + 251 "</xsl:template> " + LINE_SEP + 252 "<!-- consume 'return' and apply --> " + LINE_SEP + 253 "<xsl:template match='" + xmlaPrefix + "return'> " + LINE_SEP + 254 "<xsl:apply-templates/> " + LINE_SEP + 255 "</xsl:template> " + LINE_SEP + 256 "<!-- consume 'root' and apply --> " + LINE_SEP + 257 "<xsl:template match='ROW:root'> " + LINE_SEP + 258 "<xsl:apply-templates/> " + LINE_SEP + 259 "</xsl:template> " + LINE_SEP + 260 "<!-- consume 'row' --> " + LINE_SEP + 261 "<xsl:template match='ROW:row'> " + LINE_SEP + 262 "</xsl:template> " + LINE_SEP + 263 "<!-- copy everything else --> " + LINE_SEP + 264 "<xsl:template match='*|@*'> " + LINE_SEP + 265 "<xsl:copy> " + LINE_SEP + 266 "<xsl:apply-templates select='@*|node()'/> " + LINE_SEP + 267 "</xsl:copy> " + LINE_SEP + 268 "</xsl:template> " + LINE_SEP + 269 "</xsl:stylesheet>"; 270 } 271 272 275 public static class SAXErrorHandler implements ErrorHandler { 276 public static final String WARNING_STRING = "WARNING"; 277 public static final String ERROR_STRING = "ERROR"; 278 public static final String FATAL_ERROR_STRING = "FATAL"; 279 280 public static final short SEVERITY_WARNING = 1; 282 public static final short SEVERITY_ERROR = 2; 283 public static final short SEVERITY_FATAL_ERROR = 3; 284 285 public void printErrorInfos(PrintStream out) { 286 if (errors != null) { 287 for (ErrorInfo error : errors) { 288 out.println(formatErrorInfo(error)); 289 } 290 } 291 } 292 293 public static String formatErrorInfos(SAXErrorHandler saxEH) { 294 if (! saxEH.hasErrors()) { 295 return ""; 296 } 297 StringBuilder buf = new StringBuilder (512); 298 for (ErrorInfo error : saxEH.getErrors()) { 299 buf.append(formatErrorInfo(error)); 300 buf.append(LINE_SEP); 301 } 302 return buf.toString(); 303 } 304 305 public static String formatErrorInfo(ErrorInfo ei) { 306 StringBuilder buf = new StringBuilder (128); 307 buf.append("["); 308 switch (ei.severity) { 309 case SEVERITY_WARNING: 310 buf.append(WARNING_STRING); 311 break; 312 case SEVERITY_ERROR: 313 buf.append(ERROR_STRING); 314 break; 315 case SEVERITY_FATAL_ERROR: 316 buf.append(FATAL_ERROR_STRING); 317 break; 318 } 319 buf.append(']'); 320 String systemId = ei.exception.getSystemId(); 321 if (systemId != null) { 322 int index = systemId.lastIndexOf('/'); 323 if (index != -1) { 324 systemId = systemId.substring(index + 1); 325 } 326 buf.append(systemId); 327 } 328 buf.append(':'); 329 buf.append(ei.exception.getLineNumber()); 330 buf.append(':'); 331 buf.append(ei.exception.getColumnNumber()); 332 buf.append(": "); 333 buf.append(ei.exception.getMessage()); 334 return buf.toString(); 335 } 336 public static class ErrorInfo { 337 public SAXParseException exception; 338 public short severity; 339 ErrorInfo(short severity, SAXParseException exception) { 340 this.severity = severity; 341 this.exception = exception; 342 } 343 } 344 private List<ErrorInfo> errors; 345 public SAXErrorHandler() { 346 } 347 public List<ErrorInfo> getErrors() { 348 return this.errors; 349 } 350 public boolean hasErrors() { 351 return (this.errors != null); 352 } 353 public void warning(SAXParseException exception) throws SAXException { 354 addError(new ErrorInfo(SEVERITY_WARNING, exception)); 355 } 356 public void error(SAXParseException exception) throws SAXException { 357 addError(new ErrorInfo(SEVERITY_ERROR, exception)); 358 } 359 public void fatalError(SAXParseException exception) 360 throws SAXException { 361 addError(new ErrorInfo(SEVERITY_FATAL_ERROR, exception)); 362 } 363 protected void addError(ErrorInfo ei) { 364 if (this.errors == null) { 365 this.errors = new ArrayList<ErrorInfo>(); 366 } 367 this.errors.add(ei); 368 } 369 370 public String getFirstError() { 371 return (hasErrors()) 372 ? formatErrorInfo(errors.get(0)) 373 : ""; 374 } 375 } 376 377 public static Document newDocument(Node firstElement, boolean deepcopy) { 378 Document newDoc = new DocumentImpl(); 379 newDoc.appendChild(newDoc.importNode(firstElement, deepcopy)); 380 return newDoc; 381 } 382 383 384 388 393 public static DOMParser getParser( 394 String schemaLocationPropertyValue, 395 EntityResolver entityResolver, 396 boolean validate) 397 throws SAXNotRecognizedException, SAXNotSupportedException { 398 399 boolean doingValidation = 400 (validate || (schemaLocationPropertyValue != null)); 401 402 DOMParser parser = new DOMParser(); 403 404 parser.setEntityResolver(entityResolver); 405 parser.setErrorHandler(new SAXErrorHandler()); 406 parser.setFeature(DEFER_NODE_EXPANSION, false); 407 parser.setFeature(NAMESPACES_FEATURE_ID, true); 408 parser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, doingValidation); 409 parser.setFeature(VALIDATION_FEATURE_ID, doingValidation); 410 411 if (schemaLocationPropertyValue != null) { 412 parser.setProperty(SCHEMA_LOCATION, 413 schemaLocationPropertyValue.replace('\\', '/')); 414 } 415 416 return parser; 417 } 418 419 424 private static void checkForParseError(final DOMParser parser, Throwable t) { 425 final ErrorHandler errorHandler = parser.getErrorHandler(); 426 427 if (errorHandler instanceof SAXErrorHandler) { 428 final SAXErrorHandler saxEH = (SAXErrorHandler) errorHandler; 429 final List<SAXErrorHandler.ErrorInfo> errors = saxEH.getErrors(); 430 431 if (errors != null && errors.size() > 0) { 432 String errorStr = SAXErrorHandler.formatErrorInfos(saxEH); 433 throw new RuntimeException (errorStr, t); 434 } 435 } else { 436 System.out.println("errorHandler=" +errorHandler); 437 } 438 } 439 440 private static void checkForParseError(final DOMParser parser) { 441 checkForParseError(parser, null); 442 } 443 444 445 449 public static Document parseString(String s) 450 throws SAXException, IOException { 451 final int length = s.length(); 453 454 if (length > 16777216 && length % 4 == 1) { 455 final StringBuilder buf = new StringBuilder (length + 1); 456 457 buf.append(s); 458 buf.append('\n'); 459 s = buf.toString(); 460 } 461 462 return XmlUtil.parse(s.getBytes()); 463 } 464 465 469 public static Document parse(byte[] bytes) 470 throws SAXException, IOException { 471 return XmlUtil.parse(new ByteArrayInputStream(bytes)); 472 } 473 474 public static Document parse(File file) 475 throws SAXException, IOException { 476 477 return parse(new FileInputStream(file)); 478 } 479 480 484 public static Document parse(InputStream in) 485 throws SAXException, IOException { 486 487 InputSource source = new InputSource(in); 488 489 DOMParser parser = XmlUtil.getParser(null, null, false); 490 try { 491 parser.parse(source); 492 checkForParseError(parser); 493 } catch (SAXParseException ex) { 494 checkForParseError(parser, ex); 495 } 496 497 Document document = parser.getDocument(); 498 return document; 499 } 500 501 502 519 public static Document createContextDocument(String [][] nsArray) 520 throws SAXException, IOException { 521 StringBuilder buf = new StringBuilder (256); 522 buf.append("<?xml version='1.0' encoding='utf-8'?>"); 523 buf.append("<DOES_NOT_MATTER"); 524 for (int i = 0; i < nsArray.length; i++) { 525 String prefix = nsArray[i][0]; 526 String nsURI = nsArray[i][1]; 527 528 buf.append(" xmlns:"); 529 buf.append(prefix); 530 buf.append("=\""); 531 buf.append(nsURI); 532 buf.append("\""); 533 } 534 buf.append(" />"); 535 536 String docStr = buf.toString(); 537 return parseString(docStr); 538 } 539 540 public static String makeSoapPath() { 541 return XmlUtil.makeSoapPath(SOAP_PREFIX); 542 } 543 544 public static String makeSoapPath(String prefix) { 546 StringBuilder buf = new StringBuilder (20); 547 buf.append('/'); 548 if (prefix != null) { 549 buf.append(prefix); 550 buf.append(':'); 551 } 552 buf.append("Envelope"); 553 buf.append('/'); 554 if (prefix != null) { 555 buf.append(prefix); 556 buf.append(':'); 557 } 558 buf.append("Body"); 559 buf.append('/'); 560 buf.append('*'); 561 562 return buf.toString(); 563 } 564 565 public static String makeRootPathInSoapBody() { 566 return makeRootPathInSoapBody("xmla", XSD_PREFIX); 567 } 568 569 public static String makeRootPathInSoapBody( 571 String xmlaPrefix, 572 String xsdPrefix) 573 { 574 StringBuilder buf = new StringBuilder (20); 575 buf.append("/").append(xmlaPrefix).append(":DiscoverResponse"); 576 buf.append("/").append(xmlaPrefix).append(":return"); 577 buf.append("/ROW:root"); 578 buf.append('/'); 579 buf.append('*'); 580 587 588 return buf.toString(); 589 } 590 591 public static String selectAsString(Node node, String xpath) 592 throws XPathException { 593 return XmlUtil.selectAsString(node, xpath, node); 594 } 595 public static String selectAsString(Node node, String xpath, 596 Node namespaceNode) throws XPathException { 597 598 XPathResult xpathResult = XmlUtil.select(node, xpath, namespaceNode); 599 return XmlUtil.convertToString(xpathResult, false); 600 } 601 602 public static Node[] selectAsNodes(Node node, String xpath) 603 throws XPathException { 604 return XmlUtil.selectAsNodes(node, xpath, node); 605 } 606 public static Node[] selectAsNodes(Node node, String xpath, 607 Node namespaceNode) throws XPathException { 608 609 XPathResult xpathResult = XmlUtil.select(node, xpath, namespaceNode); 610 return XmlUtil.convertToNodes(xpathResult); 611 } 612 613 public static XPathResult select(Node contextNode, String xpath, 614 Node namespaceNode) throws XPathException { 615 XPathEvaluator evaluator = new XPathEvaluatorImpl(); 616 XPathNSResolver resolver = evaluator.createNSResolver(namespaceNode); 617 618 return (XPathResult) evaluator.evaluate(xpath, contextNode, resolver, 619 XPathResult.ANY_TYPE, null); 620 } 621 622 626 public static String convertToString(XPathResult xpathResult, 627 boolean prettyPrint) { 628 switch (xpathResult.getResultType()) { 629 case XPathResult.NUMBER_TYPE: 630 double d = xpathResult.getNumberValue(); 631 return Double.toString(d); 632 633 case XPathResult.STRING_TYPE: 634 String s = xpathResult.getStringValue(); 635 return s; 636 637 case XPathResult.BOOLEAN_TYPE: 638 boolean b = xpathResult.getBooleanValue(); 639 return String.valueOf(b); 640 641 case XPathResult.FIRST_ORDERED_NODE_TYPE: 642 case XPathResult.ANY_UNORDERED_NODE_TYPE: { 643 Node node = xpathResult.getSingleNodeValue(); 644 return XmlUtil.toString(node, prettyPrint); 645 } 646 case XPathResult.ORDERED_NODE_ITERATOR_TYPE: 647 case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: { 648 StringBuilder buf = new StringBuilder (512); 649 Node node = xpathResult.iterateNext(); 650 while (node != null) { 651 buf.append(XmlUtil.toString(node, prettyPrint)); 652 node = xpathResult.iterateNext(); 653 } 654 return buf.toString(); 655 } 656 case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE: 657 case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE: { 658 StringBuilder buf = new StringBuilder (512); 659 int len = xpathResult.getSnapshotLength(); 660 for (int i = 0; i < len; i++) { 661 Node node = xpathResult.snapshotItem(i); 662 buf.append(XmlUtil.toString(node, prettyPrint)); 663 } 664 return buf.toString(); 665 } 666 default: 667 String msg = "Unknown xpathResult.type = " 668 + xpathResult.getResultType(); 669 throw new XPathException(XPathException.TYPE_ERR ,msg); 670 } 671 } 672 673 private static final Node[] NULL_NODE_ARRAY = new Node[0]; 674 675 679 public static Node[] convertToNodes(XPathResult xpathResult) { 680 switch (xpathResult.getResultType()) { 681 case XPathResult.NUMBER_TYPE: 682 return NULL_NODE_ARRAY; 683 684 case XPathResult.STRING_TYPE: 685 return NULL_NODE_ARRAY; 686 687 case XPathResult.BOOLEAN_TYPE: 688 return NULL_NODE_ARRAY; 689 690 case XPathResult.FIRST_ORDERED_NODE_TYPE: 691 case XPathResult.ANY_UNORDERED_NODE_TYPE: { 692 Node node = xpathResult.getSingleNodeValue(); 693 return new Node[] { node }; 694 } 695 case XPathResult.ORDERED_NODE_ITERATOR_TYPE: 696 case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: { 697 List<Node> list = new ArrayList<Node>(); 698 Node node = xpathResult.iterateNext(); 699 while (node != null) { 700 list.add(node); 701 node = xpathResult.iterateNext(); 702 } 703 return (Node[]) list.toArray(NULL_NODE_ARRAY); 704 } 705 case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE: 706 case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE: { 707 int len = xpathResult.getSnapshotLength(); 708 Node[] nodes = new Node[len]; 709 for (int i = 0; i < len; i++) { 710 Node node = xpathResult.snapshotItem(i); 711 nodes[i] = node; 712 } 713 return nodes; 714 } 715 default: 716 String msg = "Unknown xpathResult.type = " 717 + xpathResult.getResultType(); 718 throw new XPathException(XPathException.TYPE_ERR ,msg); 719 } 720 } 721 722 726 public static String toString(Node node, boolean prettyPrint) { 727 if (node == null) { 728 return null; 729 } 730 try { 731 Document doc = node.getOwnerDocument(); 732 OutputFormat format = null; 733 if (doc != null) { 734 format = new OutputFormat(doc, null, prettyPrint); 735 } else { 736 format = new OutputFormat("xml", null, prettyPrint); 737 } 738 if (prettyPrint) { 739 format.setLineSeparator(LINE_SEP); 740 } else { 741 format.setLineSeparator(""); 742 } 743 StringWriter writer = new StringWriter(1000); 744 XMLSerializer serial = new XMLSerializer(writer, format); 745 serial.asDOMSerializer(); 746 if (node instanceof Document) { 747 serial.serialize((Document) node); 748 } else if (node instanceof Element) { 749 format.setOmitXMLDeclaration(true); 750 serial.serialize((Element) node); 751 } else if (node instanceof DocumentFragment) { 752 format.setOmitXMLDeclaration(true); 753 serial.serialize((DocumentFragment) node); 754 } else if (node instanceof Text) { 755 Text text = (Text) node; 756 return text.getData(); 757 } else if (node instanceof Attr) { 758 Attr attr = (Attr) node; 759 String name = attr.getName(); 760 String value = attr.getValue(); 761 writer.write(name); 762 writer.write("=\""); 763 writer.write(value); 764 writer.write("\""); 765 if (prettyPrint) { 766 writer.write(LINE_SEP); 767 } 768 } else { 769 writer.write("node class = " +node.getClass().getName()); 770 if (prettyPrint) { 771 writer.write(LINE_SEP); 772 } else { 773 writer.write(' '); 774 } 775 writer.write("XmlUtil.toString: fix me: "); 776 writer.write(node.toString()); 777 if (prettyPrint) { 778 writer.write(LINE_SEP); 779 } 780 } 781 return writer.toString(); 782 } catch (Exception ex) { 783 return null; 785 } 786 } 787 788 792 796 public static class Resolver implements EntityResolver { 797 private InputSource source; 798 799 protected Resolver() { 800 this((InputSource) null); 801 } 802 public Resolver(Document doc) { 803 this(XmlUtil.toString(doc, false)); 804 } 805 public Resolver(String str) { 806 this(new InputSource(new StringReader(str))); 807 } 808 public Resolver(InputSource source) { 809 this.source = source; 810 } 811 public InputSource resolveEntity(String publicId, 812 String systemId) 813 throws SAXException, IOException { 814 819 return source; 820 } 821 } 822 823 828 public static String getXercesVersion() { 829 try { 830 return org.apache.xerces.impl.Version.getVersion(); 831 } catch (java.lang.NoClassDefFoundError ex) { 832 return "Xerces-J 2.2.0"; 833 } 834 } 835 836 841 public static String getXercesVersionNumberString() { 842 String version = getXercesVersion(); 843 int index = version.indexOf(' '); 844 return (index == -1) 845 ? "0.0.0" : version.substring(index+1); 846 } 847 848 protected static int[] versionNumbers = null; 849 850 857 public static int[] getXercesVersionNumbers() { 858 if (versionNumbers == null) { 859 int[] verNums = new int[3]; 860 String verNumStr = getXercesVersionNumberString(); 861 int index = verNumStr.indexOf('.'); 862 verNums[0] = Integer.parseInt(verNumStr.substring(0, index)); 863 864 verNumStr = verNumStr.substring(index+1); 865 index = verNumStr.indexOf('.'); 866 verNums[1] = Integer.parseInt(verNumStr.substring(0, index)); 867 868 verNumStr = verNumStr.substring(index+1); 869 verNums[2] = Integer.parseInt(verNumStr); 870 871 versionNumbers = verNums; 872 } 873 874 return versionNumbers; 875 876 } 877 878 884 private static final String ALWAYS_ATTEMPT_VALIDATION = 885 "mondrian.xml.always.attempt.validation"; 886 private static final boolean alwaysAttemptValidation; 887 static { 888 alwaysAttemptValidation = 889 Boolean.getBoolean(ALWAYS_ATTEMPT_VALIDATION); 890 } 891 900 public static boolean supportsValidation() { 901 if (alwaysAttemptValidation) { 902 return true; 903 } else { 904 int[] verNums = getXercesVersionNumbers(); 905 return ((verNums[0] >= 3) || 906 ((verNums[0] == 2) && (verNums[1] >= 6))); 907 } 908 } 909 public static void validate(Document doc, 910 String schemaLocationPropertyValue, 911 EntityResolver resolver) 912 throws IOException , 913 SAXException, 914 SAXNotRecognizedException { 915 916 OutputFormat format = new OutputFormat(doc, null, true); 917 StringWriter writer = new StringWriter(1000); 918 XMLSerializer serial = new XMLSerializer(writer, format); 919 serial.asDOMSerializer(); 920 serial.serialize(doc); 921 String docString = writer.toString(); 922 923 validate(docString, schemaLocationPropertyValue, resolver); 924 } 925 926 945 946 public static void validate(String docStr, 947 String schemaLocationPropertyValue, 948 EntityResolver resolver) 949 throws IOException , 950 SAXException, 951 SAXNotRecognizedException { 952 if (resolver == null) { 953 resolver = new Resolver(); 954 } 955 DOMParser parser = 956 getParser(schemaLocationPropertyValue, resolver, true); 957 958 try { 959 parser.parse(new InputSource(new StringReader(docStr))); 960 checkForParseError(parser); 961 } catch (SAXParseException ex) { 962 checkForParseError(parser, ex); 963 } 964 965 } 966 967 998 999 1003 public static String getNamespaceAttributeValue(Document doc) { 1004 Element el = doc.getDocumentElement(); 1005 String prefix = el.getPrefix(); 1006 Attr attr = (prefix == null) 1007 ? el.getAttributeNode(XMLNS) 1008 : el.getAttributeNode(XMLNS + ':' + prefix); 1009 return (attr == null) ? null : attr.getValue(); 1010 } 1011 1012 1016 private static TransformerFactory tfactory = null; 1017 public static TransformerFactory getTransformerFactory() 1018 throws TransformerFactoryConfigurationError { 1019 if (tfactory == null) { 1020 tfactory = TransformerFactory.newInstance(); 1021 } 1022 return tfactory; 1023 } 1024 1025 1029 public static Node transform(Document inDoc, 1030 String xslFileName, 1031 String [][] namevalueParameters) 1032 throws ParserConfigurationException, 1033 SAXException, 1034 IOException, 1035 TransformerConfigurationException, 1036 TransformerException { 1037 1038 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 1039 dfactory.setNamespaceAware(true); 1040 1041 DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); 1042 Node xslDOM = docBuilder.parse(new InputSource(xslFileName)); 1043 1044 TransformerFactory tfactory = getTransformerFactory(); 1045 Templates stylesheet = tfactory.newTemplates( 1046 new DOMSource (xslDOM, xslFileName)); 1047 Transformer transformer = stylesheet.newTransformer(); 1048 if (namevalueParameters != null) { 1049 for (int i = 0; i < namevalueParameters.length; i++) { 1050 String name = namevalueParameters[i][0]; 1051 String value = namevalueParameters[i][1]; 1052 1053 transformer.setParameter(name, value); 1054 } 1055 } 1056 DOMResult domResult = new DOMResult (); 1057 transformer.transform(new DOMSource (inDoc, null), domResult); 1058 1059 return domResult.getNode(); 1060 } 1061 public static Node transform(Document inDoc, 1062 String xslFileName) 1063 throws ParserConfigurationException, 1064 SAXException, 1065 IOException, 1066 TransformerConfigurationException, 1067 TransformerException { 1068 return transform(inDoc, xslFileName, null); 1069 } 1070 1071 1075 public static Node transform(Document inDoc, 1076 Reader xslReader, 1077 String [][] namevalueParameters) 1078 throws ParserConfigurationException, 1079 SAXException, 1080 IOException, 1081 TransformerConfigurationException, 1082 TransformerException { 1083 1084 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 1085 dfactory.setNamespaceAware(true); 1086 1087 DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); 1088 Node xslDOM = docBuilder.parse(new InputSource(xslReader)); 1089 1090 TransformerFactory tfactory = getTransformerFactory(); 1091 Templates stylesheet = tfactory.newTemplates(new DOMSource (xslDOM)); 1092 Transformer transformer = stylesheet.newTransformer(); 1093 if (namevalueParameters != null) { 1094 for (int i = 0; i < namevalueParameters.length; i++) { 1095 String name = namevalueParameters[i][0]; 1096 String value = namevalueParameters[i][1]; 1097 1098 transformer.setParameter(name, value); 1099 } 1100 } 1101 1102 DOMResult domResult = new DOMResult (); 1103 transformer.transform(new DOMSource (inDoc, null), domResult); 1104 1105 return domResult.getNode(); 1106 } 1107 public static Node transform(Document inDoc, 1108 Reader xslReader) 1109 throws ParserConfigurationException, 1110 SAXException, 1111 IOException, 1112 TransformerConfigurationException, 1113 TransformerException { 1114 return transform(inDoc, xslReader, null); 1115 } 1116 1117 1118 private XmlUtil() {} 1119} 1120 1121 | Popular Tags |