001 /* 002 * Common usable utilities 003 * 004 * Copyright (c) 2006 005 * Petr Hadraba <hadrabap@bluetone.cz> 006 * 007 * Author: Petr Hadraba 008 * 009 * -- 010 * 011 * XML Utilities 012 */ 013 014 package global.sandbox.xmlutilities; 015 016 import java.io.BufferedInputStream; 017 import java.io.File; 018 import java.io.FileInputStream; 019 import java.io.FileNotFoundException; 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.io.StringWriter; 023 import java.util.Iterator; 024 import java.util.Map; 025 026 import javax.xml.XMLConstants; 027 import javax.xml.namespace.NamespaceContext; 028 import javax.xml.parsers.DocumentBuilder; 029 import javax.xml.parsers.DocumentBuilderFactory; 030 import javax.xml.parsers.ParserConfigurationException; 031 import javax.xml.transform.Source; 032 import javax.xml.transform.Templates; 033 import javax.xml.transform.Transformer; 034 import javax.xml.transform.TransformerConfigurationException; 035 import javax.xml.transform.TransformerException; 036 import javax.xml.transform.TransformerFactory; 037 import javax.xml.transform.stream.StreamResult; 038 import javax.xml.validation.SchemaFactory; 039 import javax.xml.validation.Validator; 040 import javax.xml.xpath.XPath; 041 import javax.xml.xpath.XPathConstants; 042 import javax.xml.xpath.XPathExpressionException; 043 import javax.xml.xpath.XPathFactory; 044 import javax.xml.xpath.XPathFactoryConfigurationException; 045 046 import org.w3c.dom.Document; 047 import org.w3c.dom.Node; 048 import org.w3c.dom.NodeList; 049 import org.xml.sax.SAXException; 050 051 /** 052 * This class provides simple XML utilities. 053 * 054 * @author Petr Hadraba 055 * 056 * @version 1.1 057 */ 058 public class XMLUtilities { 059 060 /** 061 * stores schema factory 062 */ 063 private final SchemaFactory schemaFactory; 064 065 /** 066 * stores document builder factory 067 */ 068 private final DocumentBuilderFactory documentBuilderFactory; 069 070 /** 071 * stores document builder 072 */ 073 private final DocumentBuilder documentBuilder; 074 075 /** 076 * stores localTransformer factory 077 */ 078 private final TransformerFactory transformerFactory; 079 080 /** 081 * stores localTransformer 082 */ 083 private final Transformer transformer; 084 085 /** 086 * stores XPath factory 087 */ 088 private final XPathFactory xpathFactory; 089 090 /** 091 * stores xpath evaluator 092 */ 093 private final XPath xpath; 094 095 /** 096 * stores the default NamespaceContext 097 */ 098 private final NamespaceContext defaultNamespaceContext; 099 100 /** 101 * initializes XMLUtilities 102 * 103 * Creates new factories and new instanties 104 * 105 * @throws ParserConfigurationException 106 * @throws TransformerConfigurationException 107 * @throws XPathFactoryConfigurationException 108 */ 109 public XMLUtilities() throws ParserConfigurationException, 110 TransformerConfigurationException, 111 XPathFactoryConfigurationException { 112 this(null, null, null, null, null, null, null, null); 113 } 114 115 /** 116 * initializes XMLUtilities 117 * 118 * Creates new factories and new instaties according to custom objects. 119 * 120 * @param documentBuilderFactory 121 * custom DocumentBuilderFactory 122 * @param documentBuilder 123 * custom DocumentBuilder 124 * @param schemaFactory 125 * custom SchemaFactory 126 * @param transformerFactory 127 * custom TransformerFactory 128 * @param transformer 129 * custom Transformer 130 * @param xpathFactory 131 * custom XPathFactory 132 * @param xpath 133 * custom XPath 134 * @param defaultNamespaceContext 135 * custom namespaces 136 * 137 * @throws ParserConfigurationException 138 * @throws TransformerConfigurationException 139 * @throws XPathFactoryConfigurationException 140 */ 141 public XMLUtilities(final DocumentBuilderFactory documentBuilderFactory, 142 final DocumentBuilder documentBuilder, 143 final SchemaFactory schemaFactory, 144 final TransformerFactory transformerFactory, 145 final Transformer transformer, final XPathFactory xpathFactory, 146 final XPath xpath, final NamespaceContext defaultNamespaceContext) 147 throws ParserConfigurationException, 148 TransformerConfigurationException, 149 XPathFactoryConfigurationException { 150 super(); 151 152 if (documentBuilderFactory == null) { 153 this.documentBuilderFactory = DocumentBuilderFactory.newInstance(); 154 this.documentBuilderFactory.setNamespaceAware(true); 155 } else { 156 this.documentBuilderFactory = documentBuilderFactory; 157 } 158 159 if (documentBuilder == null) { 160 this.documentBuilder = this.documentBuilderFactory 161 .newDocumentBuilder(); 162 } else { 163 this.documentBuilder = documentBuilder; 164 } 165 166 if (schemaFactory == null) { 167 this.schemaFactory = SchemaFactory 168 .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 169 } else { 170 this.schemaFactory = schemaFactory; 171 } 172 173 if (transformerFactory == null) { 174 this.transformerFactory = TransformerFactory.newInstance(); 175 } else { 176 this.transformerFactory = transformerFactory; 177 } 178 179 if (transformer == null) { 180 this.transformer = this.transformerFactory.newTransformer(); 181 } else { 182 this.transformer = transformer; 183 } 184 185 if (xpathFactory == null) { 186 this.xpathFactory = XPathFactory 187 .newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI); 188 } else { 189 this.xpathFactory = xpathFactory; 190 } 191 192 if (xpath == null) { 193 this.xpath = this.xpathFactory.newXPath(); 194 } else { 195 this.xpath = xpath; 196 } 197 198 if (defaultNamespaceContext == null) { 199 this.defaultNamespaceContext = new NamespaceContextImpl(); 200 } else { 201 this.defaultNamespaceContext = defaultNamespaceContext; 202 } 203 } 204 205 /** 206 * obtains SchemaFactory object internaly used by the XMLUtilities 207 * 208 * @return SchemaFactory object 209 */ 210 public SchemaFactory getSchemaFactory() { 211 return schemaFactory; 212 } 213 214 /** 215 * obtains DocumentBuilderFactory object internaly used by the XMLUtilities 216 * 217 * @return DocumentBuilderFactory object 218 */ 219 public DocumentBuilderFactory getDocumentBuilderFactory() { 220 return documentBuilderFactory; 221 } 222 223 /** 224 * obtains DocumentBuilder object internaly used by the XMLUtilities 225 * 226 * @return DocumentBuilder object 227 */ 228 public DocumentBuilder getDocumentBuilder() { 229 return documentBuilder; 230 } 231 232 /** 233 * obtains TransformerFactory object internaly used by the XMLUtilities 234 * 235 * @return TransformerFactory object 236 */ 237 public TransformerFactory getTransformerFactory() { 238 return transformerFactory; 239 } 240 241 /** 242 * obtains Transformer object internaly used by the XMLUtilities 243 * 244 * @return Transformer object 245 */ 246 public Transformer getTransformer() { 247 return transformer; 248 } 249 250 /** 251 * obtains XPathFactory object internaly used by the XMLUtilities 252 * 253 * @return XPathFactory object 254 */ 255 public XPathFactory getXPathFactory() { 256 return xpathFactory; 257 } 258 259 /** 260 * obtains XPath object internaly used by the XMLUtilities 261 * 262 * @return XPath object 263 */ 264 public XPath getXPath() { 265 return xpath; 266 } 267 268 /** 269 * obtains default NamespaceContext used by the XMLUtilities 270 * 271 * @return default NamespaceContenxt object 272 */ 273 public NamespaceContext getDefaultNamespaceContext() { 274 return defaultNamespaceContext; 275 } 276 277 /** 278 * validates XML file using XML schema 279 * 280 * @param xmlDocument 281 * document to validate 282 * @param xmlSchema 283 * XMLSchema 284 * 285 * @return null if successful, string with error otherwise 286 * 287 * @throws IOException 288 */ 289 public String validateXmlUsingSchema(final Source xmlDocument, 290 final Source xmlSchema) throws IOException { 291 final Validator validator; 292 293 try { 294 validator = schemaFactory.newSchema(xmlSchema).newValidator(); 295 296 validator.validate(xmlDocument); 297 } catch (SAXException e) { 298 return e.getMessage(); 299 } 300 301 return null; 302 } 303 304 /** 305 * loads XML from file specified with file name 306 * 307 * @param fileName 308 * file to load 309 * 310 * @return Document object 311 * 312 * @throws SAXException 313 * @throws IOException 314 * @throws FileNotFoundException 315 */ 316 public Document loadDocumentFromFile(final String fileName) 317 throws FileNotFoundException, IOException, SAXException { 318 return loadDocumentFromFile(new File(fileName)); 319 } 320 321 /** 322 * loads XML from file specified with file name 323 * 324 * @param fileName 325 * file to load 326 * @param documentBuilder 327 * custom document builder 328 * 329 * @return Document object 330 * 331 * @throws SAXException 332 * @throws IOException 333 * @throws FileNotFoundException 334 */ 335 public Document loadDocumentFromFile(final String fileName, 336 final DocumentBuilder documentBuilder) 337 throws FileNotFoundException, IOException, SAXException { 338 return loadDocumentFromFile(new File(fileName), documentBuilder); 339 } 340 341 /** 342 * loads XML from file specified with the File object 343 * 344 * @param file 345 * file to load 346 * 347 * @return Document object 348 * 349 * @throws SAXException 350 * @throws IOException 351 * @throws FileNotFoundException 352 */ 353 public Document loadDocumentFromFile(final File file) 354 throws FileNotFoundException, IOException, SAXException { 355 return loadDocumentFromFile(file, documentBuilder); 356 } 357 358 /** 359 * loads XML from file specified with the file object 360 * 361 * @param file 362 * file to load 363 * @param documentBuilder 364 * custom document builder 365 * 366 * @return Document object 367 * 368 * @throws FileNotFoundException 369 * @throws IOException 370 * @throws SAXException 371 */ 372 public Document loadDocumentFromFile(final File file, 373 final DocumentBuilder documentBuilder) 374 throws FileNotFoundException, IOException, SAXException { 375 final InputStream inputStream = new FileInputStream(file); 376 377 final Document document; 378 try { 379 document = loadDocumentFromStream(inputStream, documentBuilder); 380 } finally { 381 inputStream.close(); 382 } 383 384 return document; 385 } 386 387 /** 388 * loads XML from specified input stream 389 * 390 * @param is 391 * input stream 392 * 393 * @return Document object 394 * 395 * @throws IOException 396 * @throws SAXException 397 */ 398 public Document loadDocumentFromStream(final InputStream is) 399 throws IOException, SAXException { 400 return loadDocumentFromStream(is, documentBuilder); 401 } 402 403 /** 404 * loads XML from specified input stream 405 * 406 * @param is 407 * input stream 408 * @param documentBuilder 409 * custom Document Builder 410 * 411 * @return Document object 412 * 413 * @throws IOException 414 * @throws SAXException 415 */ 416 public Document loadDocumentFromStream(final InputStream is, 417 final DocumentBuilder documentBuilder) throws IOException, 418 SAXException { 419 final BufferedInputStream bufferedInputStream 420 = new BufferedInputStream(is); 421 422 final Document document = documentBuilder.parse(bufferedInputStream); 423 424 bufferedInputStream.close(); 425 426 return document; 427 } 428 429 /** 430 * converts XML Document into String 431 * 432 * @param source 433 * Document to convert 434 * 435 * @return XML in the String 436 * 437 * @throws TransformerException 438 * @throws IOException 439 */ 440 public String documentToString(final Document source) 441 throws TransformerException, IOException { 442 return sourceToString(XMLTools.documentToDOMSource(source)); 443 } 444 445 /** 446 * converts XML Source into String 447 * 448 * @param source 449 * Document to convert 450 * 451 * @return XML in the String 452 * 453 * @throws TransformerException 454 * @throws IOException 455 */ 456 public String sourceToString(final Source source) 457 throws TransformerException, IOException { 458 final StringWriter stringWriter = new StringWriter(); 459 final StreamResult streamResult = new StreamResult(stringWriter); 460 461 transformer.setParameter("", ""); 462 transformer.clearParameters(); 463 //localTransformer.reset(); 464 465 transformer.transform(source, streamResult); 466 467 final String result = stringWriter.toString(); 468 469 stringWriter.close(); 470 471 return result; 472 } 473 474 /** 475 * evaluates specified XPath expression on specified contenxt node 476 * 477 * @param query 478 * XPath expression 479 * @param context 480 * context node 481 * 482 * @return NodeList or null if no matches 483 * 484 * @throws XPathExpressionException 485 */ 486 public NodeList evaluateXPath(final String query, final Node context) 487 throws XPathExpressionException { 488 return evaluateXPath(query, context, null); 489 } 490 491 /** 492 * evaluates specified XPath expression on specified contenxt node 493 * 494 * @param query 495 * XPath expression 496 * @param context 497 * context node 498 * @param namespaces 499 * namespace context 500 * 501 * @return NodeList or null if no matches 502 * 503 * @throws XPathExpressionException 504 */ 505 public NodeList evaluateXPath(final String query, final Node context, 506 final NamespaceContext namespaces) throws XPathExpressionException { 507 xpath.reset(); 508 509 if (namespaces == null) { 510 xpath.setNamespaceContext(defaultNamespaceContext); 511 } else { 512 xpath.setNamespaceContext(namespaces); 513 } 514 515 return (NodeList) xpath 516 .evaluate(query, context, XPathConstants.NODESET); 517 } 518 519 /** 520 * evaluates specified XPath expression and returnes first Node if XPath has 521 * matches 522 * 523 * @param query 524 * XPath expression 525 * @param context 526 * context node 527 * 528 * @return first node or null 529 * 530 * @throws XPathExpressionException 531 */ 532 public Node getFirstNodeForXPath(final String query, final Node context) 533 throws XPathExpressionException { 534 return getFirstNodeForXPath(query, context, null); 535 } 536 537 /** 538 * evaluates specified XPath expression and returnes first Node if XPath has 539 * matches 540 * 541 * @param query 542 * XPath expression 543 * @param context 544 * context node 545 * @param namespaces 546 * namespace context 547 * 548 * @return first node or null 549 * 550 * @throws XPathExpressionException 551 */ 552 public Node getFirstNodeForXPath(final String query, final Node context, 553 NamespaceContext namespaces) throws XPathExpressionException { 554 final NodeList nodes = evaluateXPath(query, context, namespaces); 555 556 if (nodes == null) { 557 return null; 558 } 559 560 if (nodes.getLength() > 0) { 561 return nodes.item(0); 562 } 563 564 return null; 565 } 566 567 /** 568 * transformes specified XML source using specified XSLT template 569 * 570 * @param xsltTemplate 571 * template to use 572 * @param document 573 * source XML document 574 * @param parameters 575 * parameters to propagate to the localTransformer 576 * 577 * @return resulting XML in the <code>String</code> 578 * 579 * @throws TransformerConfigurationException 580 * @throws TransformerException 581 */ 582 public String transformToString(final Source xsltTemplate, 583 final Source document, final Map<String, Object> parameters) 584 throws TransformerConfigurationException, TransformerException { 585 final Transformer localTransformer = transformerFactory 586 .newTransformer(xsltTemplate); 587 588 if (parameters != null) { 589 final Iterator<String> it = parameters.keySet().iterator(); 590 591 while (it.hasNext()) { 592 final String parameterName = it.next(); 593 594 localTransformer.setParameter(parameterName, parameters 595 .get(parameterName)); 596 } 597 } 598 599 final StringWriter sw = new StringWriter(); 600 final StreamResult sr = new StreamResult(sw); 601 602 localTransformer.transform(document, sr); 603 604 final String result = sw.toString(); 605 606 try { 607 sw.close(); 608 } catch (IOException e) { 609 return null; 610 } 611 612 return result; 613 } 614 615 /** 616 * transforms specified XML source using specified XSLT (compiled) template 617 * 618 * @param xsltTemplate 619 * template to use 620 * @param document 621 * source XML document to transform 622 * @param parameters 623 * parameters to propagate to the localTransformer 624 * 625 * @return resulting XML in the <code>String</code> 626 * 627 * @throws TransformerException 628 */ 629 public String transformToString(final Templates xsltTemplate, 630 final Source document, final Map<String, Object> parameters) 631 throws TransformerException { 632 final Transformer localTransformer = xsltTemplate.newTransformer(); 633 634 if (parameters != null) { 635 final Iterator<String> it = parameters.keySet().iterator(); 636 637 while (it.hasNext()) { 638 final String parameterName = it.next(); 639 640 localTransformer.setParameter(parameterName, parameters 641 .get(parameterName)); 642 } 643 } 644 645 final StringWriter sw = new StringWriter(); 646 final StreamResult sr = new StreamResult(sw); 647 648 localTransformer.transform(document, sr); 649 650 final String result = sw.toString(); 651 652 try { 653 sw.close(); 654 } catch (IOException e) { 655 return null; 656 } 657 658 return result; 659 } 660 661 /** 662 * transforms specified XML source using specified XSLT (compiled) template 663 * 664 * @param xsltTemplate 665 * template to use 666 * @param document 667 * source XML document to transform 668 * 669 * @return resulting XML in the <code>String</code> 670 * 671 * @throws TransformerException 672 */ 673 public String transformToString(final Templates xsltTemplate, 674 final Source document) throws TransformerException { 675 return transformToString(xsltTemplate, document, null); 676 } 677 678 /** 679 * transformes specified XML document using specified XSLT template 680 * 681 * @param xsltTemplate 682 * XSLT template 683 * @param document 684 * source XML document 685 * 686 * @return resulting XML document in the <code>String</code> 687 * 688 * @throws TransformerConfigurationException 689 * @throws TransformerException 690 */ 691 public String transformToString(final Source xsltTemplate, 692 final Source document) throws TransformerConfigurationException, 693 TransformerException { 694 return transformToString(xsltTemplate, document, null); 695 } 696 697 /** 698 * transformes specified XML document using specified XSLT template 699 * 700 * @param xsltTemplate 701 * XSLT template 702 * @param document 703 * source XML document 704 * @return resulting XML document in the <code>Document</code> 705 * 706 * @throws TransformerConfigurationException 707 * @throws XPathFactoryConfigurationException 708 * @throws ParserConfigurationException 709 * @throws SAXException 710 * @throws IOException 711 * @throws TransformerException 712 */ 713 public Document transformToDocument(final Source xsltTemplate, 714 final Source document) throws TransformerConfigurationException, 715 XPathFactoryConfigurationException, ParserConfigurationException, 716 SAXException, IOException, TransformerException { 717 final XMLUtilities xmlUtils = new XMLUtilities(); 718 719 return XMLTools.loadDocumentFromString(transformToString(xsltTemplate, 720 document, null), xmlUtils); 721 } 722 723 /** 724 * transforms specified XML document using XSLT (compiled) template 725 * 726 * @param xsltTemplate 727 * template to use 728 * @param document 729 * document to transform 730 * 731 * @return resulting XML document in the <code>Document</code> 732 * 733 * @throws TransformerConfigurationException 734 * @throws XPathFactoryConfigurationException 735 * @throws ParserConfigurationException 736 * @throws SAXException 737 * @throws IOException 738 * @throws TransformerException 739 */ 740 public Document transformToDocument(final Templates xsltTemplate, 741 final Source document) throws TransformerConfigurationException, 742 XPathFactoryConfigurationException, ParserConfigurationException, 743 SAXException, IOException, TransformerException { 744 final XMLUtilities xmlUtils = new XMLUtilities(); 745 746 return XMLTools.loadDocumentFromString(transformToString(xsltTemplate, 747 document, null), xmlUtils); 748 } 749 750 /** 751 * transformes specified XML document using specified XSLT template 752 * 753 * @param xsltTemplate 754 * XSLT template 755 * @param document 756 * source XML document 757 * @param parameters 758 * parameters for the template 759 * @return resulting XML document in the <code>Document</code> 760 * 761 * @throws TransformerConfigurationException 762 * @throws XPathFactoryConfigurationException 763 * @throws ParserConfigurationException 764 * @throws SAXException 765 * @throws IOException 766 * @throws TransformerException 767 */ 768 public Document transformToDocument(final Source xsltTemplate, 769 final Source document, final Map<String, Object> parameters) 770 throws TransformerConfigurationException, 771 XPathFactoryConfigurationException, ParserConfigurationException, 772 SAXException, IOException, TransformerException { 773 final XMLUtilities xmlUtils = new XMLUtilities(); 774 775 return XMLTools.loadDocumentFromString(transformToString(xsltTemplate, 776 document, parameters), xmlUtils); 777 } 778 779 /** 780 * transforms sepecified XML using XSLT (compiled) template 781 * 782 * @param xsltTemplate 783 * template to use 784 * @param document 785 * XML document to transform 786 * @param parameters 787 * parameters for the transformation 788 * 789 * @return resulting XML document in the <code>Document</code> 790 * 791 * @throws TransformerConfigurationException 792 * @throws XPathFactoryConfigurationException 793 * @throws ParserConfigurationException 794 * @throws SAXException 795 * @throws IOException 796 * @throws TransformerException 797 */ 798 public Document transformToDocument(final Templates xsltTemplate, 799 final Source document, final Map<String, Object> parameters) 800 throws TransformerConfigurationException, 801 XPathFactoryConfigurationException, ParserConfigurationException, 802 SAXException, IOException, TransformerException { 803 final XMLUtilities xmlUtils = new XMLUtilities(); 804 805 return XMLTools.loadDocumentFromString(transformToString(xsltTemplate, 806 document, parameters), xmlUtils); 807 } 808 809 }