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 }