001 // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/framework/xml/XMLFragment.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2006 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53115 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 043 ---------------------------------------------------------------------------*/ 044 045 package org.deegree.framework.xml; 046 047 import java.io.File; 048 import java.io.IOException; 049 import java.io.InputStream; 050 import java.io.InputStreamReader; 051 import java.io.OutputStream; 052 import java.io.PushbackInputStream; 053 import java.io.PushbackReader; 054 import java.io.Reader; 055 import java.io.Serializable; 056 import java.io.StringWriter; 057 import java.io.Writer; 058 import java.net.MalformedURLException; 059 import java.net.URI; 060 import java.net.URISyntaxException; 061 import java.net.URL; 062 import java.util.HashMap; 063 import java.util.Map; 064 import java.util.NoSuchElementException; 065 import java.util.Properties; 066 import java.util.StringTokenizer; 067 068 import javax.xml.parsers.DocumentBuilder; 069 import javax.xml.parsers.DocumentBuilderFactory; 070 import javax.xml.parsers.ParserConfigurationException; 071 import javax.xml.transform.OutputKeys; 072 import javax.xml.transform.Source; 073 import javax.xml.transform.Transformer; 074 import javax.xml.transform.TransformerConfigurationException; 075 import javax.xml.transform.TransformerException; 076 import javax.xml.transform.TransformerFactory; 077 import javax.xml.transform.dom.DOMSource; 078 import javax.xml.transform.stream.StreamResult; 079 080 import org.deegree.datatypes.QualifiedName; 081 import org.deegree.datatypes.xlink.SimpleLink; 082 import org.deegree.framework.log.ILogger; 083 import org.deegree.framework.log.LoggerFactory; 084 import org.deegree.framework.util.BootLogger; 085 import org.deegree.framework.util.CharsetUtils; 086 import org.deegree.framework.util.StringTools; 087 import org.deegree.model.feature.Messages; 088 import org.deegree.ogcbase.CommonNamespaces; 089 import org.w3c.dom.Document; 090 import org.w3c.dom.Element; 091 import org.w3c.dom.NamedNodeMap; 092 import org.w3c.dom.Node; 093 import org.xml.sax.InputSource; 094 import org.xml.sax.SAXException; 095 096 /** 097 * An instance of <code>XMLFragment</code> encapsulates an underlying {@link Element} which acts 098 * as the root element of the document (which may be a fragment or a whole document). 099 * <p> 100 * Basically, <code>XMLFragment</code> provides easy loading and proper saving (automatically 101 * generated CDATA-elements for text nodes that need to be escaped) and acts as base class for all 102 * XML parsers in deegree. 103 * 104 * TODO: automatically generated CDATA-elements are not implemented yet 105 * 106 * <p> 107 * Additionally, <code>XMLFragment</code> tries to make the handling of relative paths inside the 108 * document's content as painless as possible. This means that after initialization of the 109 * <code>XMLFragment</code> with the correct SystemID (i.e. the URL of the document): 110 * <ul> 111 * <li>external parsed entities (in the DOCTYPE part) can use relative URLs; e.g. <!ENTITY local 112 * SYSTEM "conf/wfs/wfs.cfg"></li> 113 * <li>application specific documents which extend <code>XMLFragment</code> can resolve relative 114 * URLs during parsing by calling the <code>resolve()</code> method</li> 115 * </ul> 116 * 117 * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a> 118 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a> 119 * @author last edited by: $Author: aschmitz $ 120 * 121 * @version $Revision: 6853 $, $Date: 2007-05-07 15:28:10 +0200 (Mo, 07 Mai 2007) $ 122 * 123 * @see org.deegree.framework.xml.XMLTools 124 */ 125 126 public class XMLFragment implements Serializable { 127 128 private static final long serialVersionUID = 8984447437613709386L; 129 130 protected static NamespaceContext nsContext = CommonNamespaces.getNamespaceContext(); 131 132 protected static final URI XLNNS = CommonNamespaces.XLNNS; 133 134 protected static final ILogger LOG = LoggerFactory.getLogger( XMLFragment.class ); 135 136 /** 137 * Use this URL as SystemID only if an <code>XMLFragment</code> cannot be pinpointed to a URL - 138 * in this case it may not use any relative references! 139 */ 140 public static final String DEFAULT_URL = "http://www.deegree.org"; 141 142 private URL systemId; 143 144 private Element rootElement; 145 146 private static final String PRETTY_PRINTER_RESOURCE = "PrettyPrinter.xsl"; 147 148 private static XSLTDocument PRETTY_PRINTER_XSLT = new XSLTDocument(); 149 150 static { 151 LOG.logDebug( "DOM implementation in use (DocumentBuilderFactory): " 152 + DocumentBuilderFactory.newInstance().getClass().getName() ); 153 try { 154 LOG.logDebug( "DOM implementation in use (DocumentBuilder): " 155 + DocumentBuilderFactory.newInstance().newDocumentBuilder().getClass().getName() ); 156 } catch ( Exception e ) { 157 BootLogger.logError( "Error creating test DocumentBuilder instance.", e ); 158 } 159 try { 160 URL url = XMLFragment.class.getResource( PRETTY_PRINTER_RESOURCE ); 161 if ( url == null ) { 162 throw new IOException( "The resource '" + PRETTY_PRINTER_RESOURCE + " could not be found." ); 163 } 164 PRETTY_PRINTER_XSLT.load( url ); 165 } catch ( Exception e ) { 166 BootLogger.logError( "Error loading PrettyPrinter-XSLT document: " + e.getMessage(), e ); 167 } 168 } 169 170 /** 171 * Creates a new <code>XMLFragment</code> which is not initialized. 172 */ 173 public XMLFragment() { 174 // nothing to do 175 } 176 177 /** 178 * Creates a new <code>XMLFragment</code> which is loaded from the given <code>URL</code>. 179 * 180 * @param url 181 * @throws IOException 182 * @throws SAXException 183 */ 184 public XMLFragment( URL url ) throws IOException, SAXException { 185 load( url ); 186 } 187 188 /** 189 * Creates a new <code>XMLFragment</code> which is loaded from the given <code>File</code>. 190 * 191 * @param file 192 * the file to load from 193 * @throws SAXException 194 * if the document could not be parsed 195 * @throws IOException 196 * if the document could not be read 197 * @throws MalformedURLException 198 * if the file cannot be transposed to a valid url 199 */ 200 public XMLFragment( File file ) throws MalformedURLException, IOException, SAXException { 201 if ( file != null ) { 202 load( file.toURI().toURL() ); 203 } 204 } 205 206 /** 207 * Creates a new <code>XMLFragment</code> which is loaded from the given <code>Reader</code>. 208 * 209 * @param reader 210 * @param systemId 211 * this string should represent a URL that is related to the passed reader. If this 212 * URL is not available or unknown, the string should contain the value of 213 * XMLFragment.DEFAULT_URL 214 * @throws SAXException 215 * @throws IOException 216 */ 217 public XMLFragment( Reader reader, String systemId ) throws SAXException, IOException { 218 load( reader, systemId ); 219 } 220 221 /** 222 * Creates a new <code>XMLFragment</code> instance based on the submitted 223 * <code>Document</code>. 224 * 225 * @param doc 226 * @param systemId 227 * this string should represent a URL that is the source of the passed doc. If this 228 * URL is not available or unknown, the string should contain the value of 229 * XMLFragment.DEFAULT_URL 230 * @throws MalformedURLException 231 * if systemId is no valid and absolute <code>URL</code> 232 */ 233 public XMLFragment( Document doc, String systemId ) throws MalformedURLException { 234 setRootElement( doc.getDocumentElement() ); 235 setSystemId( systemId ); 236 } 237 238 /** 239 * Creates a new <code>XMLFragment</code> instance based on the submitted <code>Element</code>. 240 * 241 * @param element 242 */ 243 public XMLFragment( Element element ) { 244 setRootElement( element ); 245 } 246 247 /** 248 * Constructs an empty document with the given <code>QualifiedName</code> as root node. 249 * 250 * @param elementName 251 * if the name's namespace is set, the prefix should be set as well. 252 */ 253 public XMLFragment( QualifiedName elementName ) { 254 try { 255 DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 256 if ( elementName.getNamespace() == null ) { 257 rootElement = db.newDocument().createElement( elementName.getLocalName() ); 258 } else { 259 String pre = elementName.getPrefix(); 260 String ns = elementName.getNamespace().toString(); 261 if ( pre == null || pre.trim().length() == 0 ) { 262 pre = "dummy"; 263 LOG.logWarning( StringTools.concat( 200, "Incorrect usage of deegree API,", 264 " prefix of a root node was not ", "defined:\nNode name was ", 265 elementName.getLocalName(), ", namespace was ", ns ) ); 266 } 267 String name = StringTools.concat( 200, pre, ":", elementName.getLocalName() ); 268 rootElement = db.newDocument().createElementNS( ns, name ); 269 rootElement.setAttribute( "xmlns:" + pre, ns ); 270 } 271 } catch ( ParserConfigurationException e ) { 272 LOG.logError( "The parser seems to be misconfigured. Broken installation?", e ); 273 } 274 } 275 276 /** 277 * Returns the systemId (the URL of the <code>XMLFragment</code>). 278 * 279 * @return the systemId 280 */ 281 public URL getSystemId() { 282 return systemId; 283 } 284 285 /** 286 * @param systemId 287 * The systemId (physical location) to set (may be null). 288 * @throws MalformedURLException 289 */ 290 public void setSystemId( String systemId ) 291 throws MalformedURLException { 292 if ( systemId != null ) { 293 this.systemId = new URL( systemId ); 294 } 295 } 296 297 /** 298 * @param systemId 299 * The systemId (physical location) to set. 300 */ 301 public void setSystemId( URL systemId ) { 302 this.systemId = systemId; 303 } 304 305 /** 306 * Returns whether the document has a schema reference. 307 * 308 * @return true, if the document has a schema reference, false otherwise 309 */ 310 public boolean hasSchema() { 311 if ( this.rootElement.getAttribute( "xsi:schemaLocation" ) != null ) { 312 return true; 313 } 314 return false; 315 } 316 317 /** 318 * Determines the namespace <code>URI</code>s and the bound schema <code>URL</code>s from 319 * the 'xsi:schemaLocation' attribute of the document element. 320 * 321 * @return keys are URIs (namespaces), values are URLs (schema locations) 322 * @throws XMLParsingException 323 */ 324 public Map<URI, URL> getAttachedSchemas() 325 throws XMLParsingException { 326 327 Map<URI, URL> schemaMap = new HashMap<URI, URL>(); 328 329 NamedNodeMap attrMap = rootElement.getAttributes(); 330 Node schemaLocationAttr = attrMap.getNamedItem( "xsi:schemaLocation" ); 331 if ( schemaLocationAttr == null ) { 332 return schemaMap; 333 } 334 335 String target = schemaLocationAttr.getNodeValue(); 336 StringTokenizer tokenizer = new StringTokenizer( target ); 337 338 while ( tokenizer.hasMoreTokens() ) { 339 URI nsURI = null; 340 String token = tokenizer.nextToken(); 341 try { 342 nsURI = new URI( token ); 343 } catch ( URISyntaxException e ) { 344 String msg = "Invalid 'xsi:schemaLocation' attribute: namespace " + token + "' is not a valid URI."; 345 LOG.logError( msg ); 346 throw new XMLParsingException( msg ); 347 } 348 349 URL schemaURL = null; 350 try { 351 token = tokenizer.nextToken(); 352 schemaURL = resolve( token ); 353 } catch ( NoSuchElementException e ) { 354 String msg = "Invalid 'xsi:schemaLocation' attribute: namespace '" + nsURI 355 + "' is missing a schema URL."; 356 LOG.logError( msg ); 357 throw new XMLParsingException( msg ); 358 } catch ( MalformedURLException ex ) { 359 String msg = "Invalid 'xsi:schemaLocation' attribute: '" + token + "' for namespace '" + nsURI 360 + "' could not be parsed as URL."; 361 throw new XMLParsingException( msg ); 362 } 363 schemaMap.put( nsURI, schemaURL ); 364 } 365 return schemaMap; 366 } 367 368 /** 369 * Initializes the <code>XMLFragment</code> with the content from the given <code>URL</code>. 370 * Sets the SystemId, too. 371 * 372 * @param url 373 * @throws IOException 374 * @throws SAXException 375 */ 376 public void load( URL url ) 377 throws IOException, SAXException { 378 String uri = url.toExternalForm(); 379 load( url.openStream(), uri ); 380 } 381 382 /** 383 * Initializes the <code>XMLFragment</code> with the content from the given 384 * <code>InputStream</code>. Sets the SystemId, too. 385 * 386 * @param istream 387 * @param systemId 388 * cannot be null. This string should represent a URL that is related to the passed 389 * istream. If this URL is not available or unknown, the string should contain the 390 * value of XMLFragment.DEFAULT_URL 391 * @throws SAXException 392 * @throws IOException 393 * @throws XMLException 394 * @throws NullPointerException 395 */ 396 public void load( InputStream istream, String systemId ) 397 throws SAXException, IOException, XMLException { 398 399 PushbackInputStream pbis = new PushbackInputStream( istream, 1024 ); 400 String encoding = readEncoding( pbis ); 401 402 InputStreamReader isr = new InputStreamReader( pbis, encoding ); 403 load( isr, systemId ); 404 } 405 406 /** 407 * reads the encoding of a XML document from its header. If no header available 408 * <code>CharsetUtils.getSystemCharset()</code> will be returned 409 * 410 * @param pbis 411 * @return encoding of a XML document 412 * @throws IOException 413 */ 414 private String readEncoding( PushbackInputStream pbis ) 415 throws IOException { 416 byte[] b = new byte[80]; 417 int rd = pbis.read( b ); 418 String s = new String( b ).toLowerCase(); 419 String encoding = CharsetUtils.getSystemCharset(); 420 if ( s.indexOf( "?>" ) > -1 ) { 421 int p = s.indexOf( "encoding=" ); 422 if ( p > -1 ) { 423 StringBuffer sb = new StringBuffer(); 424 int k = p + 1 + "encoding=".length(); 425 while ( s.charAt( k ) != '"' && s.charAt( k ) != '\'' ) { 426 sb.append( s.charAt( k++ ) ); 427 } 428 encoding = sb.toString(); 429 } 430 } 431 pbis.unread( b, 0, rd ); 432 return encoding; 433 } 434 435 /** 436 * Initializes the <code>XMLFragment</code> with the content from the given 437 * <code>Reader</code>. Sets the SystemId, too. 438 * 439 * @param reader 440 * @param systemId 441 * can not be null. This string should represent a URL that is related to the passed 442 * reader. If this URL is not available or unknown, the string should contain the 443 * value of XMLFragment.DEFAULT_URL 444 * @throws SAXException 445 * @throws IOException 446 * @throws NullPointerException 447 */ 448 public void load( Reader reader, String systemId ) 449 throws SAXException, IOException { 450 451 PushbackReader pbr = new PushbackReader( reader, 1024 ); 452 int c = pbr.read(); 453 if ( c != 65279 && c != 65534 ) { 454 // no BOM! push char back into reader 455 pbr.unread( c ); 456 } 457 458 InputSource source = new InputSource( pbr ); 459 if ( systemId == null ) { 460 throw new NullPointerException( "'systemId' must not be null!" ); 461 } 462 setSystemId( systemId ); 463 DocumentBuilder builder = XMLTools.getDocumentBuilder(); 464 Document doc = builder.parse( source ); 465 setRootElement( doc.getDocumentElement() ); 466 } 467 468 /** 469 * @param rootElement 470 */ 471 public void setRootElement( Element rootElement ) { 472 this.rootElement = rootElement; 473 } 474 475 /** 476 * @return the element 477 */ 478 public Element getRootElement() { 479 return rootElement; 480 } 481 482 /** 483 * Resolves the given URL (which may be relative) against the SystemID of the 484 * <code>XMLFragment</code> into a <code>URL</code> (which is always absolute). 485 * 486 * @param url 487 * @return the resolved URL object 488 * @throws MalformedURLException 489 */ 490 public URL resolve( String url ) 491 throws MalformedURLException { 492 LOG.logDebug( StringTools.concat( 200, "Resolving URL '", url, "' against SystemID '", systemId, 493 "' of XMLFragment" ) ); 494 // check if url is an absolut path 495 File file = new File( url ); 496 if ( file.isAbsolute() ) { 497 return file.toURL(); 498 } 499 // remove leading '/' because otherwise 500 // URL resolvedURL = new URL( systemId, url ); will fail 501 if ( url.startsWith( "/" ) ) { 502 url = url.substring( 1, url.length() ); 503 LOG.logInfo( "URL has been corrected by removing the leading '/'" ); 504 } 505 URL resolvedURL = new URL( systemId, url ); 506 507 LOG.logDebug( StringTools.concat( 100, "-> resolvedURL: '", resolvedURL, "'" ) ); 508 return resolvedURL; 509 } 510 511 /** 512 * Writes the <code>XMLFragment</code> instance to the given <code>Writer</code> using the 513 * default system encoding and adding CDATA-sections in for text-nodes where needed. 514 * 515 * TODO: Add code for CDATA safety. 516 * 517 * @param writer 518 */ 519 public void write( Writer writer ) { 520 Properties properties = new Properties(); 521 properties.setProperty( OutputKeys.ENCODING, CharsetUtils.getSystemCharset() ); 522 write( writer, properties ); 523 } 524 525 /** 526 * Writes the <code>XMLFragment</code> instance to the given <code>Writer</code> using the 527 * specified <code>OutputKeys</code>. 528 * 529 * @param writer 530 * cannot be null 531 * @param outputProperties 532 * output properties for the <code>Transformer</code> that is used to serialize the 533 * document 534 * 535 * see javax.xml.OutputKeys 536 */ 537 public void write( Writer writer, Properties outputProperties ) { 538 try { 539 Source source = new DOMSource( rootElement ); 540 Transformer transformer = TransformerFactory.newInstance().newTransformer(); 541 if ( outputProperties != null ) { 542 transformer.setOutputProperties( outputProperties ); 543 } 544 transformer.transform( source, new StreamResult( writer ) ); 545 } catch ( TransformerConfigurationException e ) { 546 LOG.logError( e.getMessage(), e ); 547 throw new XMLException( e ); 548 } catch ( Exception e ) { 549 LOG.logError( e.getMessage(), e ); 550 throw new XMLException( e ); 551 } 552 } 553 554 /** 555 * Writes the <code>XMLFragment</code> instance to the given <code>OutputStream</code> using 556 * the default system encoding and adding CDATA-sections in for text-nodes where needed. 557 * 558 * TODO: Add code for CDATA safety. 559 * 560 * @param os 561 */ 562 public void write( OutputStream os ) { 563 Properties properties = new Properties(); 564 properties.setProperty( OutputKeys.ENCODING, CharsetUtils.getSystemCharset() ); 565 write( os, properties ); 566 } 567 568 /** 569 * Writes the <code>XMLFragment</code> instance to the given <code>OutputStream</code> using 570 * the specified <code>OutputKeys</code> which allow complete control of the generated output. 571 * 572 * @param os 573 * cannot be null 574 * @param outputProperties 575 * output properties for the <code>Transformer</code> used to serialize the 576 * document 577 * 578 * @see javax.xml.transform.OutputKeys 579 */ 580 public void write( OutputStream os, Properties outputProperties ) { 581 try { 582 Source source = new DOMSource( rootElement ); 583 Transformer transformer = TransformerFactory.newInstance().newTransformer(); 584 if ( outputProperties != null ) { 585 transformer.setOutputProperties( outputProperties ); 586 } 587 transformer.transform( source, new StreamResult( os ) ); 588 } catch ( TransformerConfigurationException e ) { 589 LOG.logError( e.getMessage(), e ); 590 throw new XMLException( e ); 591 } catch ( Exception e ) { 592 LOG.logError( e.getMessage(), e ); 593 throw new XMLException( e ); 594 } 595 } 596 597 /** 598 * Writes the <code>XMLFragment</code> instance to the given <code>OutputStream</code> using 599 * indentation so it may be read easily. 600 * 601 * @param os 602 * @throws TransformerException 603 */ 604 public void prettyPrint( OutputStream os ) 605 throws TransformerException { 606 PRETTY_PRINTER_XSLT.transform( this ).write( os ); 607 } 608 609 /** 610 * Writes the <code>XMLFragment</code> instance to the given <code>Writer</code> using 611 * indentation so it may be read easily. 612 * 613 * @param writer 614 * @throws TransformerException 615 */ 616 public void prettyPrint( Writer writer ) 617 throws TransformerException { 618 PRETTY_PRINTER_XSLT.transform( this ).write( writer ); 619 } 620 621 /** 622 * Parses the submitted <code>Element</code> as a <code>SimpleLink</code>. 623 * <p> 624 * Possible escaping of the attributes "xlink:href", "xlink:role" and "xlink:arcrole" is 625 * performed automatically. 626 * </p> 627 * 628 * @param element 629 * @return the object representation of the element 630 * @throws XMLParsingException 631 */ 632 protected SimpleLink parseSimpleLink( Element element ) 633 throws XMLParsingException { 634 635 URI href = null; 636 URI role = null; 637 URI arcrole = null; 638 String title = null; 639 String show = null; 640 String actuate = null; 641 642 String uriString = null; 643 try { 644 uriString = XMLTools.getNodeAsString( element, "@xlink:href", nsContext, null ); 645 if ( uriString != null ) { 646 href = new URI( null, uriString, null ); 647 } 648 uriString = XMLTools.getNodeAsString( element, "@xlink:role", nsContext, null ); 649 if ( uriString != null ) { 650 role = new URI( null, uriString, null ); 651 } 652 uriString = XMLTools.getNodeAsString( element, "@xlink:arcrole", nsContext, null ); 653 if ( uriString != null ) { 654 arcrole = new URI( null, uriString, null ); 655 } 656 } catch ( URISyntaxException e ) { 657 throw new XMLParsingException( "'" + uriString + "' is not a valid URI." ); 658 } 659 660 return new SimpleLink( href, role, arcrole, title, show, actuate ); 661 } 662 663 /** 664 * Parses the value of the submitted <code>Node</code> as a <code>QualifiedName</code>. 665 * <p> 666 * To parse the text contents of an <code>Element</code> node, the actual text node must be 667 * given, not the <code>Element</code> node itself. 668 * </p> 669 * 670 * @param node 671 * @return object representation of the element 672 * @throws XMLParsingException 673 */ 674 public static QualifiedName parseQualifiedName( Node node ) 675 throws XMLParsingException { 676 677 String name = node.getNodeValue().trim(); 678 QualifiedName qName = null; 679 if ( name.indexOf( ':' ) > -1 ) { 680 String[] tmp = StringTools.toArray( name, ":", false ); 681 try { 682 qName = new QualifiedName( tmp[0], tmp[1], XMLTools.getNamespaceForPrefix( tmp[0], node ) ); 683 } catch ( URISyntaxException e ) { 684 throw new XMLParsingException( e.getMessage(), e ); 685 } 686 } else { 687 qName = new QualifiedName( name ); 688 } 689 return qName; 690 } 691 692 /** 693 * Returns the qualified name of the given element. 694 * 695 * @param element 696 * @return the qualified name of the given element. 697 * @throws XMLParsingException 698 */ 699 protected QualifiedName getQualifiedName( Element element ) 700 throws XMLParsingException { 701 702 // TODO check if we can use element.getNamespaceURI() instead 703 URI nsURI = null; 704 String prefix = element.getPrefix(); 705 try { 706 nsURI = XMLTools.getNamespaceForPrefix( prefix, element ); 707 } catch ( URISyntaxException e ) { 708 String msg = Messages.format( "ERROR_NSURI_NO_URI", element.getPrefix() ); 709 LOG.logError( msg, e ); 710 throw new XMLParsingException( msg, e ); 711 } 712 QualifiedName ftName = new QualifiedName( prefix, element.getLocalName(), nsURI ); 713 714 return ftName; 715 } 716 717 /** 718 * Returns a string representation of the XML Document 719 * 720 * @return the string 721 */ 722 public String getAsString() { 723 StringWriter writer = new StringWriter( 50000 ); 724 Source source = new DOMSource( rootElement ); 725 try { 726 Transformer transformer = TransformerFactory.newInstance().newTransformer(); 727 transformer.setOutputProperty( "encoding", CharsetUtils.getSystemCharset() ); 728 transformer.transform( source, new StreamResult( writer ) ); 729 } catch ( Exception e ) { 730 LOG.logError( "Error serializing XMLFragment!", e ); 731 } 732 return writer.toString(); 733 } 734 735 /** 736 * Returns a string representation of the XML Document, pretty printed. Note that pretty 737 * printing can mess up XML documents in some cases (GML, for instance). 738 * 739 * @return the string 740 */ 741 public String getAsPrettyString() { 742 StringWriter writer = new StringWriter( 50000 ); 743 try { 744 prettyPrint( writer ); 745 } catch ( TransformerException e ) { 746 LOG.logError( "Error pretty printing XMLFragment!", e ); 747 } 748 return writer.toString(); 749 } 750 751 /** 752 * Returns a string representation of the object. 753 * 754 * @return a string representation of the object. 755 */ 756 @Override 757 public String toString() { 758 return getAsString(); 759 } 760 }