|
#region Copyright
/*********************************************************************************
* Copyright (c) 2004 by Martin Friedrich *
* Permission to freely distribute, modify and compile these sources and *
* binaries as long as this copyright notice is included. *
* Use of code on your risk! *
* *******************************************************************************/
#endregion
using System;
using System.Collections;
using System.Xml;
namespace SaxParserSupport
{
namespace Impl
{
/// <summary>
/// <tt>SaxParserImpl</tt> implements the <tt>SaxParser</tt> interface. It
/// uses a <tt>System.Xml.XmlTextReader</tt> instance to do the actual parsing.
/// </summary>
public class SaxParserImpl : SaxParser
{
/// <summary>
/// Creates a new instance of <tt>SaxParserImpl</tt> from an existing
/// <tt>XmlReader</tt> instance.
/// </summary>
/// <param name="src">The <tt>XmlReader</tt> instance to used for parsing. This might
/// be a validating <tt>XmlReader</tt>.</param>
public SaxParserImpl( System.Xml.XmlReader src )
{
_source = src;
}
/// <summary>
/// Creates a new instance of <tt>SaxParserImpl</tt> which will read from an existing stream.
/// This stream must support reading.
/// </summary>
/// <remarks>
/// The <tt>XmlReader</tt> instance created internally will not do validation. To support
/// validation, use class <tt>SaxParserSupport.Impl.SaxValidatingParser</tt>tt>
/// instead.
/// </remarks>
/// <param name="src">The stream to be created from.</param>
/// <exception cref="System.NotSupportedException">Thrown if the stream doesn't support
/// reading</exception>
public SaxParserImpl( System.IO.Stream src )
{
_source = createXmlReader( src );
}
/// <summary>
/// Parses XML data from stream <tt>src</tt>.
/// </summary>
/// <exception cref="System.NotSupportedException">Thrown if <tt>src</tt> does
/// not support read operations.</exception>
/// <exception cref="System.InvalidOperationException">Thrown if the
/// <tt>RootElement</tt>-property is not set.</exception>
/// <exception cref="System.Xml.XmlException">Thrown by <tt>XmlReader</tt>
/// instance if XML content is invalid.</exception>
/// <remarks>In addition to the exceptions mentioned above, this method may
/// throw any IO-related exception.</remarks>
public void parse( System.IO.Stream src )
{
if ( !src.CanRead ) throw new System.NotSupportedException( "read operation on stream "
+ "not allowed" );
_source = createXmlReader( src );
parse();
}
/// <summary>
/// Parses the XML data from the currently set <i>XmlReader</i>. The
/// <tt>XmlReader</tt> is set directly at creation or indirectly by
/// <tt>SaxParserSupport.SaxParserImpl.parse(System.IO.Stream)</tt> or
/// the appropriate ctor.
/// </summary>
/// <exception cref="System.InvalidOperationException">Thrown if the
/// <tt>RootElement</tt>-property is not set.</exception>
/// <exception cref="System.Xml.XmlException">Thrown by <tt>XmlReader</tt>
/// instance if XML content is invalid.</exception>
/// <remarks>In addition to the exceptions mentioned above, this method may
/// throw any IO-related exception.</remarks>
public void parse()
{
if ( _elementStack.Count != 0 )
throw new System.InvalidOperationException( "element stack is not empty" );
bool startdocument = true;
while( _source.Read() )
{
switch ( _source.NodeType )
{
case System.Xml.XmlNodeType.Attribute:
((XMLSimpleElement )_elementStack.Peek()).setAttribute( _source.Name, _source.Value );
break;
case System.Xml.XmlNodeType.Element:
if ( startdocument )
{
startdocument = false;
RootElement.setName( _source.Name );
}
else
{
XMLSimpleElement top = (XMLSimpleElement )_elementStack.Peek();
if ( top is XMLElement )
{
XMLElement top2 = (XMLElement )top;
XMLSimpleElement child = top2.lookupElement( _source.NamespaceURI + ":" + _source.LocalName );
child.setName( _source.Name );
child.setOwner( top2 );
_elementStack.Push( child );
}
}
XMLSimpleElement current = (XMLSimpleElement )_elementStack.Peek();
int n = _source.AttributeCount;
for ( int i = 0; i < n; i ++ )
{
_source.MoveToAttribute( i );
current.setAttribute( _source.Name, _source.Value );
}
_source.MoveToElement();
// if ( ! ( current is XMLElement ) )
if ( _source.IsEmptyElement )
{
current.onElementEnd( current.getOwner() );
_elementStack.Pop();
}
break;
case System.Xml.XmlNodeType.EndElement:
{
XMLSimpleElement top = (XMLSimpleElement )_elementStack.Peek();
top.onElementEnd( top.getOwner() );
_elementStack.Pop();
}
break;
case System.Xml.XmlNodeType.Text:
((XMLElement )_elementStack.Peek()).onText( _source.Value );
break;
case System.Xml.XmlNodeType.Whitespace:
((XMLElement )_elementStack.Peek()).onWhitespace( _source.Value );
break;
case System.Xml.XmlNodeType.SignificantWhitespace:
((XMLElement )_elementStack.Peek()).onSignificantWhitespace( _source.Value );
break;
case System.Xml.XmlNodeType.XmlDeclaration:
if ( RootElement == null ) throw new System.InvalidOperationException( "no root element \'"
+ _source.Name + " \' is given" );
else _elementStack.Push( RootElement );
int m = _source.AttributeCount;
for ( int i = 0; i < m; i ++ )
{
_source.MoveToAttribute( i );
switch ( _source.Name )
{
case "version":
RootElement.setVersion( _source.Value );
break;
case "encoding":
RootElement.setEncoding( _source.Value );
break;
default:
break;
}
}
_source.MoveToElement();
break;
}
}
}
/// <summary>
/// Creates a <tt>XmlReader</tt> from a stream to be used for XML parsing.
/// To change characteristics of the <tt>XmlReader</tt> used, override this
/// method.
/// <seealso cref="SaxParserSupport.Impl.SaxValidatingParserImpl"/>
/// </summary>
/// <param name="input">The stream to be read from</param>
/// <returns>An instance of class <tt>System.Xml.XmlTextReader</tt></returns>
protected virtual System.Xml.XmlReader createXmlReader( System.IO.Stream input )
{
return new XmlTextReader( input );
}
/// <summary>
/// The <tt>XMLElement</tt> instance representing the root element
/// of the XML content.
/// </summary>
public SaxParserSupport.XMLDocument RootElement
{
get
{
return _rootelement;
}
set
{
_rootelement = value;
}
}
/// <summary>
/// ***PRIVATE***
/// </summary>
private XmlReader _source;
/// <summary>
/// ***PRIVATE***
/// </summary>
private Stack _elementStack = new Stack();
/// <summary>
/// ***PRIVATE***
/// </summary>
private XMLDocument _rootelement;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Still lacking an university degree in computer science, I have 20 years of experience in software development and implementation. Having expert knowledge in object-oriented programming languages like C++, Java and C# on Windows, LINUX and UNIX platforms, I participated in multiple research projects at the University of Oldenburg. During these assignments, I was trusted with implementation of a graphical editor for specification languages like CSP or Z and a prototypical tool for workflow data distribution and analysis. I gained experiences in a widespread spectrum of CS and software development topics, ranging from compiler construction across data base programming to MDA. My research interests include questions of graphical user interface design and component-based systems.
I consider myself an old-school CS geek. While I admit that simple tasks do not pose much of a problem and can be done in quick and efficient manner, it's the challenging ones that appeal to me. If you are looking for a skillful employee - be it on a permanent, contract or freelance basis - and if you can live with a lacking university degree, why not contacting me?