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