namespace System.Xml
{
- public class XmlDocument : XmlNode
+ public class XmlDocument : XmlNode, IHasXmlChildNode
{
#region Fields
+ static readonly Type [] optimal_create_types = new Type [] {typeof (string), typeof (string), typeof (string)};
+ bool optimal_create_element, optimal_create_attribute;
XmlNameTable nameTable;
string baseURI = String.Empty;
XmlResolver resolver;
Hashtable idTable = new Hashtable ();
XmlNameEntryCache nameCache;
+ XmlLinkedNode lastLinkedChild;
+ XmlAttribute nsNodeXml;
#if NET_2_0
XmlSchemaSet schemas;
IXmlSchemaInfo schemaInfo;
nameCache = new XmlNameEntryCache (nameTable);
AddDefaultNameTableKeys ();
resolver = new XmlUrlResolver ();
+
+ Type type = GetType ();
+ optimal_create_element = type.GetMethod ("CreateElement", optimal_create_types).DeclaringType == typeof (XmlDocument);
+ optimal_create_attribute = type.GetMethod ("CreateAttribute", optimal_create_types).DeclaringType == typeof (XmlDocument);
}
#endregion
#region Properties
+ internal XmlAttribute NsNodeXml {
+ get {
+ if (nsNodeXml == null) {
+ nsNodeXml = CreateAttribute ("xmlns", "xml", "http://www.w3.org/2000/xmlns/");
+ nsNodeXml.Value = "http://www.w3.org/XML/1998/namespace";
+ }
+ return nsNodeXml;
+ }
+ }
+
+ XmlLinkedNode IHasXmlChildNode.LastLinkedChild {
+ get { return lastLinkedChild; }
+ set { lastLinkedChild = value; }
+ }
+
public override string BaseURI {
get {
return baseURI;
public virtual XmlDocumentType DocumentType {
get {
- for (XmlNode n = FirstChild; n != null; n = n.NextSibling)
- if(n.NodeType == XmlNodeType.DocumentType)
- return (XmlDocumentType)n;
+ for (XmlNode n = FirstChild; n != null; n = n.NextSibling) {
+ if (n.NodeType == XmlNodeType.DocumentType)
+ return (XmlDocumentType) n;
+ else if (n.NodeType == XmlNodeType.Element) // document element
+ return null;
+ }
return null;
}
get { return implementation; }
}
+#if NET_4_0
+ public override string InnerText {
+ set { throw new InvalidOperationException (); }
+ }
+#endif
+
public override string InnerXml {
get {
return base.InnerXml;
}
public XmlSchemaSet Schemas {
- get { return schemas; }
+ get {
+ if (schemas == null)
+ schemas = new XmlSchemaSet ();
+ return schemas;
+ }
set { schemas = value; }
}
public virtual XmlAttribute CreateAttribute (string prefix, string localName, string namespaceURI)
{
- return CreateAttribute (prefix, localName, namespaceURI, false, true);
+ if ((localName == null) || (localName == String.Empty))
+ throw new ArgumentException ("The attribute local name cannot be empty.");
+
+ return new XmlAttribute (prefix, localName, namespaceURI, this, false, true);
}
internal XmlAttribute CreateAttribute (string prefix, string localName, string namespaceURI, bool atomizedNames, bool checkNamespace)
{
- if ((localName == null) || (localName == String.Empty))
- throw new ArgumentException ("The attribute local name cannot be empty.");
-
- return new XmlAttribute (prefix, localName, namespaceURI, this, atomizedNames, checkNamespace);
+ if (optimal_create_attribute)
+ return new XmlAttribute (prefix, localName, namespaceURI, this, atomizedNames, checkNamespace);
+ else
+ return CreateAttribute (prefix, localName, namespaceURI);
}
public virtual XmlCDataSection CreateCDataSection (string data)
string localName,
string namespaceURI)
{
- if ((localName == null) || (localName == String.Empty))
- throw new ArgumentException ("The local name for elements or attributes cannot be null or an empty string.");
// LAMESPEC: MS.NET has a weird behavior that they can Load() from XmlTextReader
// whose Namespaces = false, but their CreateElement() never allows qualified name.
// I leave it as it is.
return new XmlElement (prefix != null ? prefix : String.Empty, localName, namespaceURI != null ? namespaceURI : String.Empty, this, false);
}
+ internal XmlElement CreateElement (
+ string prefix,
+ string localName,
+ string namespaceURI,
+ bool nameAtomized)
+ {
+ if ((localName == null) || (localName == String.Empty))
+ throw new ArgumentException ("The local name for elements or attributes cannot be null or an empty string.");
+ if (optimal_create_element)
+ // LAMESPEC: MS.NET has a weird behavior that they can Load() from XmlTextReader
+ // whose Namespaces = false, but their CreateElement() never allows qualified name.
+ // I leave it as it is.
+ return new XmlElement (prefix != null ? prefix : String.Empty, localName, namespaceURI != null ? namespaceURI : String.Empty, this, nameAtomized);
+ else
+ return CreateElement (prefix, localName, namespaceURI);
+ }
+
public virtual XmlEntityReference CreateEntityReference (string name)
{
return new XmlEntityReference (name, this);
return df;
case XmlNodeType.DocumentType:
- throw new XmlException ("DocumentType cannot be imported.");
+ return ((XmlDocumentType) node).CloneNode (deep);
case XmlNodeType.Element:
XmlElement src = (XmlElement)node;
{
XmlTextReader reader = new XmlTextReader (inStream, NameTable);
reader.XmlResolver = resolver;
- Load (reader);
+ XmlValidatingReader vr = new XmlValidatingReader (reader);
+ vr.EntityHandling = EntityHandling.ExpandCharEntities;
+ vr.ValidationType = ValidationType.None;
+ Load (vr);
}
public virtual void Load (string filename)
try {
xr = new XmlTextReader (filename, NameTable);
xr.XmlResolver = resolver;
- Load (xr);
+ XmlValidatingReader vr = new XmlValidatingReader (xr);
+ vr.EntityHandling = EntityHandling.ExpandCharEntities;
+ vr.ValidationType = ValidationType.None;
+ Load (vr);
} finally {
if (xr != null)
xr.Close ();
public virtual void Load (TextReader txtReader)
{
XmlTextReader xr = new XmlTextReader (txtReader, NameTable);
+ XmlValidatingReader vr = new XmlValidatingReader (xr);
+ vr.EntityHandling = EntityHandling.ExpandCharEntities;
+ vr.ValidationType = ValidationType.None;
xr.XmlResolver = resolver;
- Load (xr);
+ Load (vr);
}
public virtual void Load (XmlReader xmlReader)
break;
if (preserveWhitespace || n.NodeType != XmlNodeType.Whitespace)
AppendChild (n, false);
- } while (true);
+ } while (xmlReader.NodeType != XmlNodeType.EndElement);
#if NET_2_0
if (xmlReader.Settings != null)
schemas = xmlReader.Settings.Schemas;
XmlTextReader xmlReader = new XmlTextReader (
xml,
XmlNodeType.Document,
- new XmlParserContext (NameTable, null, null, XmlSpace.None));
+ new XmlParserContext (NameTable, new XmlNamespaceManager (NameTable), null, XmlSpace.None));
try {
xmlReader.XmlResolver = resolver;
Load (xmlReader);
reader.MoveToFirstAttribute ();
else if (reader.NodeType != XmlNodeType.Attribute)
throw new InvalidOperationException (MakeReaderErrorMessage ("bad position to read attribute.", reader));
- XmlAttribute attribute = CreateAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI, false, false); // different NameTable
+ XmlAttribute attribute = CreateAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI);
#if NET_2_0
if (reader.SchemaInfo != null)
- SchemaInfo = new XmlSchemaInfo (reader.SchemaInfo);
+ SchemaInfo = reader.SchemaInfo;
#endif
bool isDefault = reader.IsDefault;
[PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
public virtual XmlNode ReadNode (XmlReader reader)
+ {
+ if (PreserveWhitespace)
+ return ReadNodeCore (reader);
+ XmlTextReader xtr = reader as XmlTextReader;
+ if (xtr != null && xtr.WhitespaceHandling ==
+ WhitespaceHandling.All) {
+ try {
+ xtr.WhitespaceHandling = WhitespaceHandling.Significant;
+ return ReadNodeCore (reader);
+ } finally {
+ xtr.WhitespaceHandling = WhitespaceHandling.All;
+ }
+ }
+ else
+ return ReadNodeCore (reader);
+ }
+
+ XmlNode ReadNodeCore (XmlReader reader)
{
switch (reader.ReadState) {
case ReadState.Interactive:
case ReadState.Initial:
#if NET_2_0
if (reader.SchemaInfo != null)
- this.SchemaInfo = new XmlSchemaInfo (reader.SchemaInfo);
+ SchemaInfo = reader.SchemaInfo;
#endif
reader.Read ();
break;
break;
case XmlNodeType.Element:
- XmlElement element = CreateElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
+ XmlElement element = CreateElement (reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.NameTable == this.NameTable);
#if NET_2_0
if (reader.SchemaInfo != null)
- SchemaInfo = new XmlSchemaInfo (reader.SchemaInfo);
+ SchemaInfo = reader.SchemaInfo;
#endif
element.IsEmpty = reader.IsEmptyElement;
// set the element's attributes.
+ for (int i = 0; i < reader.AttributeCount; i++) {
+ reader.MoveToAttribute (i);
+ element.SetAttributeNode (
+ ReadAttributeNode (reader));
+ reader.MoveToElement ();
+ }
+ // FIXME: the code below should be fine and
+ // in some XmlReaders it is much faster, but
+ // caused some breakage in sys.data test.
+ /*
if (reader.MoveToFirstAttribute ()) {
do {
element.SetAttributeNode (ReadAttributeNode (reader));
} while (reader.MoveToNextAttribute ());
reader.MoveToElement ();
}
+ */
+ reader.MoveToElement ();
int depth = reader.Depth;
- if (element.IsEmpty) {
+ if (reader.IsEmptyElement) {
n = element;
break;
}
reader.Read ();
while (reader.Depth > depth) {
- n = ReadNode (reader);
+ n = ReadNodeCore (reader);
if (preserveWhitespace || n.NodeType != XmlNodeType.Whitespace)
element.AppendChild (n, false);
}