#region Copyright 2010-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
namespace CSharpTest.Net.Html
{
///
/// Inteded to quickly read 'mostly' well-formed html text
///
public class XmlLightDocument : XmlLightElement, IXmlLightReader
{
///
/// Stores the current node stack while parsing documents
///
protected Stack _parserStack;
///
/// Returns the root element
///
public XmlLightElement Root;
///
/// Parses the document provided
///
public XmlLightDocument()
: base(null, false, ROOT, String.Empty)
{
_parserStack = new Stack();
}
///
/// Parses the document provided
///
public XmlLightDocument(string content)
: this()
{
XmlLightParser.Parse(content, XmlLightParser.AttributeFormat.Xml, this);
}
///
/// Writes the re-constructed innerXML
///
public override void WriteXml(XmlWriter wtr)
{
foreach (XmlLightElement e in Children)
e.WriteXml(wtr);
}
///
/// Writes the re-constructed document while attempting to preserve formatting
///
public override void WriteUnformatted(TextWriter wtr)
{
foreach (XmlLightElement e in Children)
e.WriteUnformatted(wtr);
}
/// Begins the processing of an xml input
public virtual void StartDocument()
{
Check.Assert(Children.Count == 0);
_parserStack.Push(this);
}
/// Begins the processing of an xml tag
public virtual void StartTag(XmlTagInfo tag)
{
XmlLightElement parent = _parserStack.Peek();
XmlLightElement e = new XmlLightElement(parent, tag);
if (Root == null && _parserStack.Count == 1)
Root = e;
if (tag.SelfClosed == false)
_parserStack.Push(e);
}
/// Ends the processing of an xml tag
public virtual void EndTag(XmlTagInfo tag)
{
XmlLightElement e = _parserStack.Pop();
if (e.TagName != tag.FullName)
throw new XmlException(String.Format("Incorrect tag closed '{0}>', expected '{1}>'", tag.FullName, e.TagName));
e.ClosingTagWhitespace = tag.EndingWhitespace;
}
/// Encountered text or whitespace in the document
public virtual void AddText(string content)
{
XmlLightElement parent = _parserStack.Peek();
new XmlLightElement(parent, true, XmlLightElement.TEXT, content);
}
/// Encountered comment in the document
public virtual void AddComment(string comment)
{
XmlLightElement parent = _parserStack.Peek();
new XmlLightElement(parent, true, XmlLightElement.COMMENT, comment);
}
/// Encountered cdata section in the document
public virtual void AddCData(string cdata)
{
XmlLightElement parent = _parserStack.Peek();
new XmlLightElement(parent, true, XmlLightElement.CDATA, cdata);
}
/// Encountered control information <! ... > in the document
public virtual void AddControl(string ctrl)
{
XmlLightElement parent = _parserStack.Peek();
new XmlLightElement(parent, true, XmlLightElement.CONTROL, ctrl);
}
/// Encountered processing instruction <? ... ?> in the document
public virtual void AddInstruction(string instruction)
{
XmlLightElement parent = _parserStack.Peek();
new XmlLightElement(parent, true, XmlLightElement.PROCESSING, instruction);
}
/// Ends the processing of an xml input
public virtual void EndDocument()
{
XmlLightElement e = _parserStack.Pop();
if (e.TagName != this.TagName)
throw new XmlException(String.Format("Tag was not closed, expected '{0}>'", e.TagName));
else if (this.Root == null)
throw new XmlException(String.Format("Root element not found."));
}
}
}