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