All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bibliothek.util.xml.XIO Maven / Gradle / Ivy

The newest version!
/*
 * Bibliothek - DockingFrames
 * Library built on Java/Swing, allows the user to "drag and drop"
 * panels containing any Swing-Component the developer likes to add.
 * 
 * Copyright (C) 2007 Benjamin Sigg
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Benjamin Sigg
 * [email protected]
 * CH - Switzerland
 */
package bibliothek.util.xml;

import java.io.*;
import java.util.LinkedList;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Class used to read and write xml-files. Clients should use
 * {@link #writeUTF(XElement, OutputStream)} and {@link #readUTF(InputStream)} to
 * guarantee maximal independence from the underlying file system.
 * @author Benjamin Sigg
 */
public class XIO {
    /**
     * Writes the contents of element into out.
     * @param element the element to write
     * @param out the stream to write into
     * @throws IOException if an I/O-error occurs
     */
    public static void write( XElement element, Appendable out ) throws IOException{
        out.append( "\n" );
        write( element, 0, out );
    }
    
    /**
     * Writes the contents of element into out using
     * the UTF-8 encoding.
     * @param element the element to write
     * @param out the stream to write into
     * @throws IOException if an I/O-error occurs
     */
    public static void writeUTF( XElement element, OutputStream out ) throws IOException{
        write( element, out, "UTF-8" );
    }
    
    /**
     * Writes the contents of element into out.
     * @param element the element to write
     * @param out the stream to write into
     * @param encoding the encoding for the characters
     * @throws IOException if an I/O-error occurs
     */
    public static void write( XElement element, OutputStream out, String encoding ) throws IOException{
        OutputStreamWriter writer = new OutputStreamWriter( out, encoding ){
            @Override
            public void close() throws IOException {
                // ignore
            }
        };
        write( element, writer );
        writer.flush();
    }

    /**
     * Reads a xml file provided from in using UTF-8
     * as encoding.
     * @param in the stream to read from
     * @return the root element
     * @throws IOException if an I/O-error occurs
     */
    public static XElement readUTF( InputStream in ) throws IOException{
        return read( in, "UTF-8" );
    }
    
    /**
     * Reads a xml file provided from in using encoding
     * as encoding.
     * @param in the stream to read from
     * @param encoding the encoding used to decode characters
     * @return the root element
     * @throws IOException if an I/O-error occurs
     */
    public static XElement read( InputStream in, String encoding ) throws IOException{
        InputStreamReader reader = new InputStreamReader( in, encoding ){
            @Override
            public void close() throws IOException {
                // ignore
            }
        };
        
        return read( new InputSource( reader ));
    }

    
    /**
     * Writes the contents of element into out.
     * @param element the element to write
     * @param tabs the number of tabs before the element
     * @param out the stream to write into
     * @throws IOException if an I/O-error occurs
     */
    private static void write( XElement element, int tabs, Appendable out ) throws IOException{
        for( int i = 0; i < tabs; i++ )
            out.append( "\t" );
        
        out.append( "<" );
        out.append( element.getName() );
        for( XAttribute attribute : element.attributes() ){
            out.append( " " );
            out.append( attribute.getName() );
            out.append( "=\"" );
            encode( attribute.getString(), out );
            out.append( "\"" );
        }
        String value = element.getValue();
        XElement[] children = element.children();
        
        if( value.length() == 0 && children.length == 0 ){
            out.append( "/>" );
        }
        else{
            out.append( ">" );
            if( value.length() > 0 ){
                if( children.length > 0 ){
                    out.append( "\n\t" );
                    for( int i = 0; i < tabs; i++ )
                        out.append( "\t" );
                }
                    
                encode( value, out );
            }
            if( children.length > 0 ){
                out.append( "\n" );
                for( XElement child : children ){
                    write( child, tabs+1, out );
                    out.append( "\n" );
                }
                
                for( int i = 0; i < tabs; i++ )
                    out.append( "\t" );
            }
            
            out.append( "" );
        }
    }
    
    /**
     * Encodes value such that it is a valid string in a xml-file.
     * @param value the value to encode
     * @param out the stream to write into
     */
    private static void encode( String value, Appendable out ) throws IOException{
        for( int i = 0, n = value.length(); i':
                    out.append( ">" );
                    break;
                case '\'':
                    out.append( "'" );
                    break;
                case '"':
                    out.append( """ );
                    break;
                case '&':
                    out.append( "&" );
                    break;
                default:
                    out.append( c );
                    break;
            }
        }
    }
    
    /**
     * Interprets text as a xml-file and reads it.
     * @param text the content to read, in xml format
     * @return the root element of text
     * @throws IOException if an I/O-error occurs
     */
    public static XElement read( CharSequence text ) throws IOException{
        InputSource in = new InputSource();
        in.setCharacterStream( new StringReader( text.toString() ) );
        return read( in );
    }
    
    /**
     * Reads a xml-file from source.
     * @param source the xml-file
     * @return the root element of the file.
     * @throws IOException if an I/O-error occurs
     */
    public static XElement read( InputSource source ) throws IOException{
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = factory.newSAXParser();
            Handler handler = new Handler();
            parser.parse( source, handler );
            return handler.getElement();
        }
        catch( ParserConfigurationException e ) {
            throw new IOException( e.getMessage() );
        }
        catch( SAXException e ) {
            throw new IOException( e.getMessage() );
        }
    }

    /**
     * Reads a xml file provided from reader.
     * @param reader the reader from which characters will be read
     * @return the root element
     * @throws IOException if an I/O-error occurs
     */
    public static XElement read( Reader reader ) throws IOException{
        return read( new InputSource( reader ));
    }
    
    /**
     * A handler used to read from a {@link SAXParser}.
     * @author Benjamin Sigg
     */
    private static class Handler extends DefaultHandler{
        /** the first element that was read */
        private XElement element;
        /** the current stack of active entries */
        private LinkedList stack = new LinkedList();
        
        /**
         * Gets the first element that was read.
         * @return the first element
         */
        public XElement getElement() {
            return element;
        }
        
        @Override
        public void startElement( String uri, String localName, String name,
                Attributes attributes ) throws SAXException {

            XElement element = new XElement( name );
            if( this.element == null ){
                this.element = element;
            }
            else{
                stack.getFirst().addElement( element );
            }
            
            stack.addFirst( element );
            
            // read the attributes
            for( int i = 0, n = attributes.getLength(); i 0 ){
                String value = new String( ch, start, length );
                String old = stack.getFirst().getValue();
                if( old != null && old.length() > 0 ){
                    value = old + value;
                }
                stack.getFirst().setValue( value );
            }
        }
        
        @Override
        public void endElement( String uri, String localName, String name )
                throws SAXException {

            XElement element = stack.removeFirst();
            element.setValue( element.getString().trim() );
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy