//
-// XmlTextReader.cs
+// System.Xml.XmlTextReader
//
// Author:
// Jason Diamond (jason@injektilo.org)
+// Adam Treat (manyoso@yahoo.com)
//
// (C) 2001, 2002 Jason Diamond http://injektilo.org/
//
// There's also no checking being done for either well-formedness
// or validity.
//
-// ParserContext and NameTables aren't being used yet.
+// NameTables aren't being used everywhere yet.
//
// Some thought needs to be given to performance. There's too many
// strings being allocated.
//
-// None of the MoveTo methods have been implemented yet.
+// Some of the MoveTo methods haven't been implemented yet.
//
// LineNumber and LinePosition aren't being tracked.
//
[MonoTODO]
public XmlTextReader (Stream input)
{
- throw new NotImplementedException ();
+ // We can share some code in the constructors (at least for this one and next 2)
+ XmlNameTable nt = new NameTable ();
+ XmlNamespaceManager nsMgr = new XmlNamespaceManager (nt);
+ parserContext = new XmlParserContext (null, nsMgr, null, XmlSpace.None);
+ Init ();
+ reader = new StreamReader (input);
}
[MonoTODO]
public XmlTextReader (string url)
{
- throw new NotImplementedException ();
+ XmlNameTable nt = new NameTable ();
+ XmlNamespaceManager nsMgr = new XmlNamespaceManager (nt);
+ parserContext = new XmlParserContext (null, nsMgr, null, XmlSpace.None);
+ Init ();
+ reader = new StreamReader(url);
}
[MonoTODO]
public XmlTextReader (TextReader input)
{
+ XmlNameTable nt = new NameTable ();
+ XmlNamespaceManager nsMgr = new XmlNamespaceManager (nt);
+ parserContext = new XmlParserContext (null, nsMgr, null, XmlSpace.None);
Init ();
reader = input;
}
[MonoTODO]
public XmlTextReader (string xmlFragment, XmlNodeType fragType, XmlParserContext context)
{
- throw new NotImplementedException ();
+ //Waiting for Validating reader for fragType rules.
+ parserContext = context;
+ Init ();
+ reader = new StringReader(xmlFragment);
}
#endregion
public override XmlNameTable NameTable
{
- get { return nameTable; }
+ get { return parserContext.NameTable; }
}
public override XmlNodeType NodeType
return attributes [thisName] as string;
}
} else if (localName == "xmlns" && namespaceURI == "http://www.w3.org/2000/xmlns/" && thisName == "xmlns")
- return attributes[thisName] as string;
+ return attributes [thisName] as string;
}
return String.Empty;
[MonoTODO]
bool IXmlLineInfo.HasLineInfo ()
{
- throw new NotImplementedException ();
+ return false;
}
public override string LookupNamespace (string prefix)
{
- return namespaceManager.LookupNamespace (prefix);
+ return parserContext.NamespaceManager.LookupNamespace (prefix);
}
[MonoTODO]
throw new NotImplementedException ();
}
- [MonoTODO]
public override bool MoveToAttribute (string name)
{
- throw new NotImplementedException ();
+ MoveToElement ();
+ bool match = false;
+
+ if (attributes == null)
+ return false;
+
+ if (orderedAttributesEnumerator == null) {
+ SaveProperties ();
+ orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
+ }
+
+ while (orderedAttributesEnumerator.MoveNext ()) {
+ if(name == orderedAttributesEnumerator.Current as string) {
+ match = true;
+ break;
+ }
+ }
+
+ if (match) {
+
+ string value = attributes [name] as string;
+ SetProperties (
+ XmlNodeType.Attribute, // nodeType
+ name, // name
+ false, // isEmptyElement
+ value, // value
+ false // clearAttributes
+ );
+ }
+
+ return match;
}
[MonoTODO]
throw new NotImplementedException ();
}
- [MonoTODO]
public override bool MoveToElement ()
{
- throw new NotImplementedException ();
+ if (orderedAttributesEnumerator != null) {
+ orderedAttributesEnumerator = null;
+ RestoreProperties ();
+ return true;
+ }
+
+ return false;
}
- [MonoTODO]
public override bool MoveToFirstAttribute ()
{
- throw new NotImplementedException ();
+ MoveToElement ();
+ return MoveToNextAttribute ();
}
- [MonoTODO]
public override bool MoveToNextAttribute ()
{
- throw new NotImplementedException ();
+ if (attributes == null)
+ return false;
+
+ if (orderedAttributesEnumerator == null) {
+ SaveProperties ();
+ orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
+ }
+
+ if (orderedAttributesEnumerator.MoveNext ()) {
+ string name = orderedAttributesEnumerator.Current as string;
+ string value = attributes [name] as string;
+ SetProperties (
+ XmlNodeType.Attribute, // nodeType
+ name, // name
+ false, // isEmptyElement
+ value, // value
+ false // clearAttributes
+ );
+ return true;
+ }
+
+ return false;
}
public override bool Read ()
}
[MonoTODO]
- public int ReadBase64 (byte[] buffer, int offset, int length)
+ public int ReadBase64 (byte [] buffer, int offset, int length)
{
throw new NotImplementedException ();
}
[MonoTODO]
- public int ReadBinHex (byte[] buffer, int offset, int length)
+ public int ReadBinHex (byte [] buffer, int offset, int length)
{
throw new NotImplementedException ();
}
[MonoTODO]
- public int ReadChars (char[] buffer, int offset, int length)
+ public int ReadChars (char [] buffer, int offset, int length)
{
throw new NotImplementedException ();
}
[MonoTODO]
public override string ReadInnerXml ()
{
- throw new NotImplementedException ();
+ // Still need a Well Formedness check.
+ // Will wait for Validating reader ;-)
+ if (NodeType == XmlNodeType.Attribute) {
+ return Value;
+ } else {
+ saveToXmlBuffer = true;
+ string startname = this.Name;
+ string endname = string.Empty;
+ readState = ReadState.Interactive;
+
+ while (startname != endname) {
+ ReadContent ();
+ endname = this.Name;
+ }
+
+ xmlBuffer.Replace(currentTag.ToString (), "");
+ saveToXmlBuffer = false;
+ string InnerXml = xmlBuffer.ToString ();
+ xmlBuffer.Length = 0;
+ return InnerXml;
+ }
}
[MonoTODO]
public override string ReadOuterXml ()
{
- throw new NotImplementedException ();
+ // Still need a Well Formedness check.
+ // Will wait for Validating reader ;-)
+ if (NodeType == XmlNodeType.Attribute) {
+ return Name+"=\""+Value+"\"";
+ } else {
+ saveToXmlBuffer = true;
+ xmlBuffer.Append(currentTag.ToString ());
+ string startname = this.Name;
+ string endname = string.Empty;
+ readState = ReadState.Interactive;
+
+ while (startname != endname) {
+ ReadContent ();
+ endname = this.Name;
+ }
+ saveToXmlBuffer = false;
+ string OuterXml = xmlBuffer.ToString ();
+ xmlBuffer.Length = 0;
+ return OuterXml;
+ }
}
[MonoTODO]
// privates
+ private XmlParserContext parserContext;
+
private TextReader reader;
private ReadState readState;
private int depth;
private bool depthDown;
- private XmlNameTable nameTable;
- private XmlNamespaceManager namespaceManager;
private bool popScope;
private XmlNodeType nodeType;
private string namespaceURI;
private bool isEmptyElement;
private string value;
+
+ private XmlNodeType saveNodeType;
+ private string saveName;
+ private string savePrefix;
+ private string saveLocalName;
+ private string saveNamespaceURI;
+ private bool saveIsEmptyElement;
+
private Hashtable attributes;
+ private ArrayList orderedAttributes;
+ private IEnumerator orderedAttributesEnumerator;
private bool returnEntityReference;
private string entityReferenceName;
- private char[] nameBuffer;
+ private char [] nameBuffer;
private int nameLength;
private int nameCapacity;
private const int initialNameCapacity = 256;
- private char[] valueBuffer;
+ private char [] valueBuffer;
private int valueLength;
private int valueCapacity;
private const int initialValueCapacity = 8192;
+ private StringBuilder xmlBuffer; // This is for Read(Inner|Outer)Xml
+ private StringBuilder currentTag; // A buffer for ReadContent for ReadOuterXml
+ private bool saveToXmlBuffer;
+
private void Init ()
{
- if (nameTable == null)
- nameTable = new NameTable ();
-
- namespaceManager = new XmlNamespaceManager (nameTable);
- popScope = false;
-
readState = ReadState.Initial;
depth = -1;
depthDown = false;
+ popScope = false;
+
nodeType = XmlNodeType.None;
name = String.Empty;
prefix = String.Empty;
localName = string.Empty;
isEmptyElement = false;
value = String.Empty;
+
attributes = new Hashtable ();
-
+ orderedAttributes = new ArrayList ();
+ orderedAttributesEnumerator = null;
+
returnEntityReference = false;
entityReferenceName = String.Empty;
- nameBuffer = new char[initialNameCapacity];
+ nameBuffer = new char [initialNameCapacity];
nameLength = 0;
nameCapacity = initialNameCapacity;
- valueBuffer = new char[initialValueCapacity];
+ valueBuffer = new char [initialValueCapacity];
valueLength = 0;
valueCapacity = initialValueCapacity;
+
+ xmlBuffer = new StringBuilder ();
+ currentTag = new StringBuilder ();
}
// Use this method rather than setting the properties
namespaceURI = LookupNamespace (prefix);
}
+ private void SaveProperties ()
+ {
+ saveNodeType = nodeType;
+ saveName = name;
+ savePrefix = prefix;
+ saveLocalName = localName;
+ saveNamespaceURI = namespaceURI;
+ saveIsEmptyElement = isEmptyElement;
+ // An element's value is always String.Empty.
+ }
+
+ private void RestoreProperties ()
+ {
+ nodeType = saveNodeType;
+ name = saveName;
+ prefix = savePrefix;
+ localName = saveLocalName;
+ namespaceURI = saveNamespaceURI;
+ isEmptyElement = saveIsEmptyElement;
+ value = String.Empty;
+ }
+
private void AddAttribute (string name, string value)
{
attributes.Add (name, value);
+ orderedAttributes.Add (name);
}
private void ClearAttributes ()
{
- if (attributes.Count > 0)
+ if (attributes.Count > 0) {
attributes.Clear ();
+ orderedAttributes.Clear ();
+ }
+
+ orderedAttributesEnumerator = null;
}
private int PeekChar ()
private int ReadChar ()
{
- return reader.Read ();
+ int ch = reader.Read ();
+ if (saveToXmlBuffer) {
+ xmlBuffer.Append ((char) ch);
+ }
+ currentTag.Append ((char) ch);
+ return ch;
}
// This should really keep track of some state so
private bool ReadContent ()
{
bool more = false;
-
+ currentTag.Length = 0;
if (popScope) {
- namespaceManager.PopScope ();
+ parserContext.NamespaceManager.PopScope ();
popScope = false;
}
SetEntityReferenceProperties ();
more = true;
} else {
- switch (PeekChar ())
+ switch (PeekChar ())
{
case '<':
ReadChar ();
// The leading '<' has already been consumed.
private void ReadStartTag ()
{
- namespaceManager.PushScope ();
+ parserContext.NamespaceManager.PushScope ();
string name = ReadName ();
SkipWhitespace ();
private void AppendNameChar (int ch)
{
CheckNameCapacity ();
- nameBuffer[nameLength++] = (char)ch;
+ nameBuffer [nameLength++] = (char)ch;
}
private void CheckNameCapacity ()
{
if (nameLength == nameCapacity) {
nameCapacity = nameCapacity * 2;
- char[] oldNameBuffer = nameBuffer;
- nameBuffer = new char[nameCapacity];
+ char [] oldNameBuffer = nameBuffer;
+ nameBuffer = new char [nameCapacity];
Array.Copy (oldNameBuffer, nameBuffer, nameLength);
}
}
private void AppendValueChar (int ch)
{
CheckValueCapacity ();
- valueBuffer[valueLength++] = (char)ch;
+ valueBuffer [valueLength++] = (char)ch;
}
private void CheckValueCapacity ()
{
if (valueLength == valueCapacity) {
valueCapacity = valueCapacity * 2;
- char[] oldValueBuffer = valueBuffer;
- valueBuffer = new char[valueCapacity];
+ char [] oldValueBuffer = valueBuffer;
+ valueBuffer = new char [valueCapacity];
Array.Copy (oldValueBuffer, valueBuffer, valueLength);
}
}
SkipWhitespace ();
if (name == "xmlns")
- namespaceManager.AddNamespace (String.Empty, value);
+ parserContext.NamespaceManager.AddNamespace (String.Empty, value);
else if (name.StartsWith ("xmlns:"))
- namespaceManager.AddNamespace (name.Substring (6), value);
+ parserContext.NamespaceManager.AddNamespace (name.Substring (6), value);
AddAttribute (name, value);
} while (PeekChar () != '/' && PeekChar () != '>' && PeekChar () != -1);