+2004-02-06 Atsushi Enomoto <atsushi@ximian.com>
+
+ * DTDValidatingReader.cs : Fixed MoveToElement() that causes incorrect
+ IsDefault and Depth.
+ * XmlAttribute.cs : Fixed .ctor(). Omit more namespace check when
+ checkNamespace = false.
+ * XmlNamedNodeMap.cs : Fixed SetNamedItem() to raise events.
+ * XmlAttributeCollection.cs : Reimplemented InsertAfter to use
+ InsertBefore() (similar to XmlNode).
+ * XmlDocument.cs : Added internal .ctor(). Reimplemented ReadNode()
+ as recursive, to make event order compatible.
+ * XmlDocumentType.cs : Use SetNamedItem() (to raise events).
+ * XmlElement.cs : Some refactory. Fixed SetAttributeNode() with
+ string name to block prefixed name.
+ * XmlEntity.cs : Don't raise events on setting contents.
+ * XmlNode.cs : Some refactory. Added raiseEvent argument to internal
+ InsertBefore().
+ * XmlEntityReference.cs : related fix for XmlNode change.
+ * XmlTextReader.cs : When the reader is on "attributes" of xmldecl or
+ doctype, Depth 1 lower than usual attribute. Split large function.
+
2004-02-05 Atsushi Enomoto <atsushi@ximian.com>
* XmlConvert.cs : ToSingle() and ToDouble() should be culture
return false;
bool b = reader.MoveToElement ();
- if (!b)
+ if (!b && !IsDefault)
return false;
currentAttribute = null;
consumedAttribute = false;
break;
case XmlTokenizedType.IDREFS:
foreach (string idref in list) {
- // FIXME: is this normalization required?
-// string each = FilterNormalization (def.Name, idref);
if (!idList.Contains (idref))
missingIDReferences.Add (idref);
}
namespaceURI = String.Empty;
// Prefix "xml" should be also checked (http://www.w3.org/XML/xml-names-19990114-errata#NE05)
- // but MS.NET ignores such case.
- if (prefix == "xmlns" || (prefix == "" && localName == "xmlns"))
- if (namespaceURI != XmlNamespaceManager.XmlnsXmlns)
- throw new ArgumentException ("Invalid attribute namespace for namespace declaration.");
- else if (prefix == "xml" && namespaceURI != XmlNamespaceManager.XmlnsXml)
+ // but MS.NET ignores such case
+ if (checkNamespace) {
+ if (prefix == "xmlns" || (prefix == "" && localName == "xmlns"))
+ if (namespaceURI != XmlNamespaceManager.XmlnsXmlns)
+ throw new ArgumentException ("Invalid attribute namespace for namespace declaration.");
+ else if (prefix == "xml" && namespaceURI != XmlNamespaceManager.XmlnsXml)
throw new ArgumentException ("Invalid attribute namespace for namespace declaration.");
+ }
// There are no means to identify the DOM is namespace-
// aware or not, so we can only check Name validity.
public virtual XmlAttribute InsertAfter (XmlAttribute newNode, XmlAttribute refNode)
{
- if(newNode.OwnerDocument != this.ownerDocument)
- throw new ArgumentException ("different document created this newNode.");
-
- ownerDocument.onNodeInserting (newNode, null);
-
- int pos = Nodes.Count + 1;
- if(refNode != null)
- {
- for(int i=0; i<Nodes.Count; i++)
- {
- XmlNode n = Nodes [i] as XmlNode;
- if(n == refNode)
- {
- pos = i + 1;
- break;
- }
- }
- if(pos > Nodes.Count)
- throw new XmlException ("refNode not found in this collection.");
+ if (refNode == null) {
+ if (Nodes.Count == 0)
+ return InsertBefore (newNode, null);
+ else
+ return InsertBefore (newNode, this [0]);
}
- else
- pos = 0;
- SetNamedItem (newNode, pos);
+ for (int i = 0; i < Nodes.Count; i++)
+ if (refNode == Nodes [i])
+ return InsertBefore (newNode, Nodes.Count == i + 1 ? null : this [i + 1]);
- ownerDocument.onNodeInserted (newNode, null);
-
- return newNode;
+ throw new ArgumentException ("refNode not found in this collection.");
}
public virtual XmlAttribute InsertBefore (XmlAttribute newNode, XmlAttribute refNode)
{
- if(newNode.OwnerDocument != ownerDocument)
+ if (newNode.OwnerDocument != ownerDocument)
throw new ArgumentException ("different document created this newNode.");
ownerDocument.onNodeInserting (newNode, null);
int pos = Nodes.Count;
- if(refNode != null)
- {
- for(int i=0; i<Nodes.Count; i++)
- {
+ if (refNode != null) {
+ for (int i = 0; i < Nodes.Count; i++) {
XmlNode n = Nodes [i] as XmlNode;
- if(n == refNode)
- {
+ if (n == refNode) {
pos = i;
break;
}
}
- if(pos == Nodes.Count)
- throw new XmlException ("refNode not found in this collection.");
+ if (pos == Nodes.Count)
+ throw new ArgumentException ("refNode not found in this collection.");
}
- SetNamedItem (newNode, pos);
+ SetNamedItem (newNode, pos, false);
ownerDocument.onNodeInserted (newNode, null);
XmlAttribute attr = node as XmlAttribute;
if (attr.OwnerElement != null)
throw new InvalidOperationException ("This attribute is already set to another element.");
+
+ ownerElement.OwnerDocument.onNodeInserting (node, ownerElement);
+
attr.SetOwnerElement (ownerElement);
- return AdjustIdenticalAttributes (node as XmlAttribute, base.SetNamedItem (node, -1) as XmlAttribute);
+ XmlNode n = AdjustIdenticalAttributes (node as XmlAttribute, base.SetNamedItem (node, -1, false));
+
+ ownerElement.OwnerDocument.onNodeInserted (node, ownerElement);
+
+ return n as XmlAttribute;
}
internal void AddIdenticalAttribute ()
}
public virtual XmlAttribute CreateAttribute (string prefix, string localName, string namespaceURI)
+ {
+ return CreateAttribute (prefix, localName, namespaceURI, 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, false, true);
+ return new XmlAttribute (prefix, localName, namespaceURI, this, atomizedNames, checkNamespace);
}
public virtual XmlCDataSection CreateCDataSection (string data)
loadMode = true;
do {
XmlNode n = ReadNode (xmlReader);
- if(n == null) break;
- AppendChild (n);
+ if (n == null)
+ break;
+ if (preserveWhitespace || n.NodeType != XmlNodeType.Whitespace)
+ AppendChild (n);
} while (true);
} finally {
loadMode = false;
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);
+ XmlAttribute attribute = CreateAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI, false, false); // different NameTable
ReadAttributeNodeValue (reader, attribute);
// Keep the current reader position
}
// Reads attribute from XmlReader and then creates attribute value children. XmlAttribute also uses this.
- internal void ReadAttributeNodeValue(XmlReader reader, XmlAttribute attribute)
+ internal void ReadAttributeNodeValue (XmlReader reader, XmlAttribute attribute)
{
- while(reader.ReadAttributeValue ()) {
- if(reader.NodeType == XmlNodeType.EntityReference)
+ while (reader.ReadAttributeValue ()) {
+ if (reader.NodeType == XmlNodeType.EntityReference)
// FIXME: if DocumentType is available, then try to resolve it.
attribute.AppendChild (CreateEntityReference (reader.Name));
// FIXME: else if(NodeType == EndEntity) -- reset BaseURI and so on -- ;
public virtual XmlNode ReadNode (XmlReader reader)
{
- XmlNode resultNode = null;
- XmlNode newNode = null;
- XmlNode currentNode = null;
-
switch (reader.ReadState) {
case ReadState.Interactive:
break;
return null;
}
- int startDepth = reader.Depth;
- bool ignoredWhitespace;
- bool reachedEOF = false;
-
- do {
- ignoredWhitespace = false;
- if (reader.ReadState != ReadState.Interactive)
- if (reachedEOF)
- throw new Exception ("XML Reader reached to end while reading node.");
- else
- reachedEOF = true;
- switch (reader.NodeType) {
-
- case XmlNodeType.Attribute:
- newNode = ReadAttributeNode (reader);
- break;
+ XmlNode n;
+ switch (reader.NodeType) {
- case XmlNodeType.CDATA:
- newNode = CreateCDataSection (reader.Value);
- if(currentNode != null)
- currentNode.AppendChild (newNode);
- break;
+ case XmlNodeType.Attribute:
+ return ReadAttributeNode (reader);
- case XmlNodeType.Comment:
- newNode = CreateComment (reader.Value);
- if(currentNode != null)
- currentNode.AppendChild (newNode);
- break;
+ case XmlNodeType.CDATA:
+ n = CreateCDataSection (reader.Value);
+ break;
- case XmlNodeType.Element:
- XmlElement element = CreateElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
- element.IsEmpty = reader.IsEmptyElement;
+ case XmlNodeType.Comment:
+ n = CreateComment (reader.Value);
+ break;
- // set the element's attributes.
- while (reader.MoveToNextAttribute ()) {
- element.SetAttributeNode (ReadAttributeNode (reader));
- }
+ case XmlNodeType.Element:
+ XmlElement element = CreateElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
+ element.IsEmpty = reader.IsEmptyElement;
+ // set the element's attributes.
+ if (reader.MoveToFirstAttribute ()) {
+ do {
+ element.SetAttributeNode (ReadAttributeNode (reader));
+ } while (reader.MoveToNextAttribute ());
reader.MoveToElement ();
+ }
- // MS.NET adds element to document after its attributes are filled.
- if(currentNode != null)
- currentNode.AppendChild (element);
- else
- resultNode = element;
-
- if (!reader.IsEmptyElement)
- currentNode = element;
+ int depth = reader.Depth;
+ if (element.IsEmpty) {
+ n = element;
break;
+ }
- case XmlNodeType.EndElement:
- if (currentNode == null)
- throw new XmlException ("Unexpected end element.");
- else if (currentNode.Name != reader.Name)
- throw new XmlException (reader as IXmlLineInfo, String.Format ("mismatch end tag. Expected {0} but found {1}", currentNode.Name, reader.Name));
- currentNode = currentNode.ParentNode;
- break;
+ reader.Read ();
+ while (reader.Depth > depth) {
+ n = ReadNode (reader);
+ if (preserveWhitespace || n.NodeType != XmlNodeType.Whitespace)
+ element.AppendChild (n);
+ }
+ n = element;
+ break;
- case XmlNodeType.EndEntity:
- break; // no operation
+ case XmlNodeType.ProcessingInstruction:
+ n = CreateProcessingInstruction (reader.Name, reader.Value);
+ break;
- case XmlNodeType.ProcessingInstruction:
- newNode = CreateProcessingInstruction (reader.Name, reader.Value);
- if(currentNode != null)
- currentNode.AppendChild (newNode);
- break;
+ case XmlNodeType.Text:
+ n = CreateTextNode (reader.Value);
+ break;
- case XmlNodeType.Text:
- newNode = CreateTextNode (reader.Value);
- if(currentNode != null)
- currentNode.AppendChild (newNode);
- break;
+ case XmlNodeType.XmlDeclaration:
+ n = CreateXmlDeclaration ("1.0" , String.Empty, String.Empty);
+ n.Value = reader.Value;
+ break;
- case XmlNodeType.XmlDeclaration:
- // empty strings are dummy, then gives over setting value contents to setter.
- newNode = CreateXmlDeclaration ("1.0" , String.Empty, String.Empty);
- ((XmlDeclaration)newNode).Value = reader.Value;
- if(currentNode != null)
- throw new XmlException (reader as IXmlLineInfo, "XmlDeclaration at invalid position.");
- break;
+ case XmlNodeType.DocumentType:
+ DTDObjectModel dtd = null;
+ XmlTextReader xtReader = reader as XmlTextReader;
+ if (xtReader != null)
+ dtd = xtReader.DTD;
+ XmlNodeReader xnReader = reader as XmlNodeReader;
+ if (xnReader != null)
+ dtd = xnReader.GetInternalParserContext ().Dtd;
+ XmlValidatingReader xvReader = reader as XmlValidatingReader;
+ if (xvReader != null)
+ dtd = xvReader.GetInternalParserContext ().Dtd;
+ IHasXmlParserContext ctxReader = reader as IHasXmlParserContext;
+ if (ctxReader != null)
+ dtd = ctxReader.ParserContext.Dtd;
+
+ if (dtd != null)
+ n = CreateDocumentType (dtd);
+ else
+ n = CreateDocumentType (reader.Name, reader ["PUBLIC"], reader ["SYSTEM"], reader.Value);
+ break;
- case XmlNodeType.DocumentType:
- if(currentNode != null)
- throw new XmlException (reader as IXmlLineInfo, "XmlDocumentType at invalid position.");
-
- DTDObjectModel dtd = null;
- XmlTextReader xtReader = reader as XmlTextReader;
- if (xtReader != null)
- dtd = xtReader.DTD;
- XmlNodeReader xnReader = reader as XmlNodeReader;
- if (xnReader != null)
- dtd = xnReader.GetInternalParserContext ().Dtd;
- XmlValidatingReader xvReader = reader as XmlValidatingReader;
- if (xvReader != null)
- dtd = xvReader.GetInternalParserContext ().Dtd;
- IHasXmlParserContext ctxReader = reader as IHasXmlParserContext;
- if (ctxReader != null)
- dtd = ctxReader.ParserContext.Dtd;
-
- if (dtd != null)
- newNode = CreateDocumentType (dtd);
- else
- newNode = CreateDocumentType (reader.Name, reader ["PUBLIC"], reader ["SYSTEM"], reader.Value);
+ case XmlNodeType.EntityReference:
+ if (this.loadMode && this.DocumentType != null &&
+ DocumentType.Entities.GetNamedItem (reader.Name) == null)
+ throw new XmlException ("Reference to undeclared entity was found.");
- break;
+ n = CreateEntityReference (reader.Name);
+ break;
- case XmlNodeType.EntityReference:
- if (this.loadMode && this.DocumentType != null &&
- DocumentType.Entities.GetNamedItem (reader.Name) == null)
- throw new XmlException ("Reference to undeclared entity was found.");
- newNode = CreateEntityReference (reader.Name);
- if(currentNode != null)
- currentNode.AppendChild (newNode);
- break;
+ case XmlNodeType.SignificantWhitespace:
+ n = CreateSignificantWhitespace (reader.Value);
+ break;
- case XmlNodeType.SignificantWhitespace:
- newNode = CreateSignificantWhitespace (reader.Value);
- if(currentNode != null)
- currentNode.AppendChild (newNode);
- break;
+ case XmlNodeType.Whitespace:
+ n = CreateWhitespace (reader.Value);
+ break;
- case XmlNodeType.Whitespace:
- if(PreserveWhitespace) {
- newNode = CreateWhitespace (reader.Value);
- if(currentNode != null)
- currentNode.AppendChild (newNode);
- }
- else
- ignoredWhitespace = true;
- break;
- }
- // Read next, except for reading attribute node.
- if (!(newNode is XmlAttribute) && !reader.Read ())
- break;
- } while (ignoredWhitespace || reader.Depth > startDepth ||
- (reader.Depth == startDepth && reader.NodeType == XmlNodeType.EndElement));
- if (startDepth < reader.Depth && reader.EOF)
- throw new XmlException ("Unexpected end of xml reader.");
- return resultNode != null ? resultNode : newNode;
+ case XmlNodeType.None:
+ return null;
+
+ default:
+ // No idea why MS does throw NullReferenceException ;-P
+ throw new NullReferenceException ("Unexpected node type " + reader.NodeType + ".");
+ }
+
+ reader.Read ();
+ return n;
}
private string MakeReaderErrorMessage (string message, XmlReader reader)
foreach (DTDEntityDeclaration decl in DTD.EntityDecls.Values) {
XmlNode n = new XmlEntity (decl.Name, decl.NotationName,
decl.PublicId, decl.SystemId, OwnerDocument);
- entities.Nodes.Add (n);
+ entities.SetNamedItem (n);
}
foreach (DTDNotationDeclaration decl in DTD.NotationDecls.Values) {
XmlNode n = new XmlNotation (decl.LocalName, decl.Prefix,
decl.PublicId, decl.SystemId, OwnerDocument);
- notations.Nodes.Add (n);
+ notations.SetNamedItem (n);
}
}\r
\r
if (FirstChild != null && FirstChild.NodeType == XmlNodeType.Text)
FirstChild.Value = value;
else {
- if(FirstChild != null) {
+ if (FirstChild != null) {
foreach (XmlNode n in ChildNodes)
this.RemoveChild (n);
}
// creates new Text node
- AppendChild(OwnerDocument.CreateTextNode(value));
+ AppendChild (OwnerDocument.CreateTextNode (value));
}
}
}
public virtual string SetAttribute (string localName, string namespaceURI, string value)
{
- XmlAttribute attr = attributes[localName, namespaceURI];
- if(attr == null)
- {
- attr = OwnerDocument.CreateAttribute(localName, namespaceURI);
+ XmlAttribute attr = attributes [localName, namespaceURI];
+ if (attr == null) {
+ attr = OwnerDocument.CreateAttribute (localName, namespaceURI);
attr.Value = value;
- attributes.SetNamedItem(attr);
+ attributes.SetNamedItem (attr);
}
else
attr.Value = value;
throw new InvalidOperationException (
"Specified attribute is already an attribute of another element.");
- XmlNode oldAttr = Attributes.SetNamedItem(newAttr);
- return oldAttr != null ? oldAttr as XmlAttribute : null;
+ return Attributes.SetNamedItem (newAttr) as XmlAttribute;
}
public virtual XmlAttribute SetAttributeNode (string localName, string namespaceURI)
{
- XmlDocument xmlDoc = this.OwnerDocument;
- XmlAttribute xmlAttribute = new XmlAttribute (String.Empty, localName, namespaceURI, xmlDoc, false, true);
- return this.attributes.Append (xmlAttribute);
+ // Note that this constraint is only for this method.
+ // SetAttribute() allows prefixed name.
+ XmlConvert.VerifyNCName (localName);
+
+ return Attributes.Append (OwnerDocument.CreateAttribute (String.Empty, localName, namespaceURI, false, true));
}
public override void WriteContentTo (XmlWriter w)
{
- foreach(XmlNode childNode in ChildNodes)
- childNode.WriteTo(w);
+ int count = ChildNodes.Count;
+ for (int i = 0; i < count; i++)
+ ChildNodes [i].WriteTo (w);
}
public override void WriteTo (XmlWriter w)
{
w.WriteStartElement (NamespaceURI == null || NamespaceURI.Length == 0 ? String.Empty : Prefix, LocalName, NamespaceURI);
- foreach(XmlAttribute attributeNode in Attributes)
- if (attributeNode.Specified)
- attributeNode.WriteTo(w);
+ for (int i = 0; i < Attributes.Count; i++)
+ if (Attributes [i].Specified)
+ Attributes [i].WriteTo(w);
+
if (IsEmpty)
w.WriteEndElement ();
else {
- WriteContentTo(w);
- w.WriteFullEndElement();
+ WriteContentTo (w);
+ w.WriteFullEndElement ();
}
}
do {
XmlNode n = OwnerDocument.ReadNode (xmlReader);
if(n == null) break;
- InsertBefore (n, null, false);
+ InsertBefore (n, null, false, false);
} while (true);
}\r
#endregion
\r
XmlEntity ent = doctype.Entities.GetNamedItem (Name) as XmlEntity;\r
if (ent == null)\r
- InsertBefore (OwnerDocument.CreateTextNode (String.Empty), null, false);\r
+ InsertBefore (OwnerDocument.CreateTextNode (String.Empty), null, false, true);\r
else {\r
ent.SetEntityContent ();\r
for (int i = 0; i < ent.ChildNodes.Count; i++)\r
- InsertBefore (ent.ChildNodes [i].CloneNode (true), null, false);\r
+ InsertBefore (ent.ChildNodes [i].CloneNode (true), null, false, true);\r
}\r
}\r
}\r
public virtual XmlNode SetNamedItem (XmlNode node)
{
- return SetNamedItem(node, -1);
+ return SetNamedItem (node, -1, true);
}
- internal XmlNode SetNamedItem (XmlNode node, int pos)
+ public virtual XmlNode SetNamedItem (XmlNode node, bool raiseEvent)
+ {
+ return SetNamedItem (node, -1, raiseEvent);
+ }
+
+ internal XmlNode SetNamedItem (XmlNode node, int pos, bool raiseEvent)
{
if (readOnly || (node.OwnerDocument != parent.OwnerDocument))
throw new ArgumentException ("Cannot add to NodeMap.");
- foreach (XmlNode x in nodeList)
- if(x.LocalName == node.LocalName && x.NamespaceURI == node.NamespaceURI) {
- nodeList.Remove (x);
- if (pos < 0)
- nodeList.Add (node);
- else
- nodeList.Insert (pos, node);
- return x;
+ if (raiseEvent)
+ parent.OwnerDocument.onNodeInserting (node, parent);
+
+ try {
+ foreach (XmlNode x in nodeList) {
+ if(x.LocalName == node.LocalName && x.NamespaceURI == node.NamespaceURI) {
+ nodeList.Remove (x);
+ if (pos < 0)
+ nodeList.Add (node);
+ else
+ nodeList.Insert (pos, node);
+ return x;
+ }
}
- if(pos < 0)
- nodeList.Add (node);
- else
- nodeList.Insert(pos, node);
- return null;
+ if(pos < 0)
+ nodeList.Add (node);
+ else
+ nodeList.Insert (pos, node);
+
+ return null;
+ } finally {
+ if (raiseEvent)
+ parent.OwnerDocument.onNodeInserted (node, parent);
+ }
+
}
internal ArrayList Nodes { get { return nodeList; } }
public virtual XmlNode InsertAfter (XmlNode newChild, XmlNode refChild)
{
- // I assume that insertAfter(n1, n2) equals to InsertBefore(n1, n2.PreviousSibling).
+ // InsertAfter(n1, n2) is equivalent to InsertBefore(n1, n2.PreviousSibling).
// I took this way because current implementation
- // Calling InsertAfter() from InsertBefore() is
- // subsequently to use 'NextSibling' which is
- // faster than 'PreviousSibling' (these children are
- // forward-only linked list).
+ // Calling InsertBefore() in this method is faster than
+ // the counterpart, since NextSibling is faster than
+ // PreviousSibling (these children are forward-only list).
XmlNode argNode = null;
- if(refChild != null)
+ if (refChild != null)
argNode = refChild.NextSibling;
- else if(ChildNodes.Count > 0)
+ else if (ChildNodes.Count > 0)
argNode = FirstChild;
return InsertBefore (newChild, argNode);
}
public virtual XmlNode InsertBefore (XmlNode newChild, XmlNode refChild)
{
- return InsertBefore (newChild, refChild, true);
+ return InsertBefore (newChild, refChild, true, true);
}
// check for the node to be one of node ancestors
return false;
}
- internal XmlNode InsertBefore (XmlNode newChild, XmlNode refChild, bool checkNodeType)
+ internal XmlNode InsertBefore (XmlNode newChild, XmlNode refChild, bool checkNodeType, bool raiseEvent)
{
if (checkNodeType)
CheckNodeInsertion (newChild, refChild);
- XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
+ XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument) this : OwnerDocument;
- ownerDoc.onNodeInserting (newChild, this);
+ if (raiseEvent)
+ ownerDoc.onNodeInserting (newChild, this);
- if(newChild.ParentNode != null)
+ if (newChild.ParentNode != null)
newChild.ParentNode.RemoveChild (newChild, checkNodeType);
- if(newChild.NodeType == XmlNodeType.DocumentFragment) {
+ if (newChild.NodeType == XmlNodeType.DocumentFragment) {
int x = newChild.ChildNodes.Count;
- for(int i=0; i<x; i++) {
+ for (int i = 0; i < x; i++) {
XmlNode n = newChild.ChildNodes [0];
this.InsertBefore (n, refChild); // recursively invokes events. (It is compatible with MS implementation.)
}
newLinkedChild.parentNode = this;
- if(refChild == null) {
- // append last, so:
- // * set nextSibling of previous lastchild to newChild
- // * set lastchild = newChild
- // * set next of newChild to firstChild
- if(LastLinkedChild != null) {
- XmlLinkedNode formerFirst = FirstChild as XmlLinkedNode;
+ if (refChild == null) {
+ // newChild is the last child:
+ // * set newChild as NextSibling of the existing lastchild
+ // * set LastChild = newChild
+ // * set NextSibling of newChild as FirstChild
+ if (LastLinkedChild != null) {
+ XmlLinkedNode formerFirst = (XmlLinkedNode) FirstChild;
LastLinkedChild.NextLinkedSibling = newLinkedChild;
LastLinkedChild = newLinkedChild;
newLinkedChild.NextLinkedSibling = formerFirst;
- }
- else {
+ } else {
LastLinkedChild = newLinkedChild;
LastLinkedChild.NextLinkedSibling = newLinkedChild; // FirstChild
}
- }
- else {
- // append not last, so:
+ } else {
+ // newChild is not the last child:
// * if newchild is first, then set next of lastchild is newChild.
// otherwise, set next of previous sibling to newChild
// * set next of newChild to refChild
XmlLinkedNode prev = refChild.PreviousSibling as XmlLinkedNode;
- if(prev == null)
+ if (prev == null)
LastLinkedChild.NextLinkedSibling = newLinkedChild;
else
prev.NextLinkedSibling = newLinkedChild;
break;
}
- ownerDoc.onNodeInserted (newChild, newChild.ParentNode);
+ if (raiseEvent)
+ ownerDoc.onNodeInserted (newChild, newChild.ParentNode);
}
return newChild;
}
if(oldChild.ParentNode != this)
throw new XmlException ("specified child is not child of this node.");
- ownerDoc.onNodeRemoving (oldChild, oldChild.ParentNode);
+ if (checkNodeType)
+ ownerDoc.onNodeRemoving (oldChild, oldChild.ParentNode);
if (checkNodeType)
CheckNodeRemoval ();
oldLinkedChild.NextLinkedSibling = null;
}
- ownerDoc.onNodeRemoved (oldChild, oldChild.ParentNode);
+ if (checkNodeType)
+ ownerDoc.onNodeRemoved (oldChild, oldChild.ParentNode);
oldChild.parentNode = null; // clear parent 'after' above logic.
return oldChild;
// FIXME:
//
-// NameTables aren't being used completely yet.
-//
// Some thought needs to be given to performance. There's too many
// strings being allocated.
//
public override int Depth
{
get {
+ int nodeTypeMod = currentToken.NodeType == XmlNodeType.Element ? 0 : -1;
if (currentAttributeValue >= 0)
- return elementDepth + 2; // inside attribute value.
+ return nodeTypeMod + elementDepth + 2; // inside attribute value.
else if (currentAttribute >= 0)
- return elementDepth + 1;
+ return nodeTypeMod + elementDepth + 1;
return elementDepth;
}
}
// The reader is positioned on the first character of
// the attribute name.
- private void ReadAttributes (bool endsWithQuestion)
+ private void ReadAttributes (bool isXmlDecl)
{
int peekChar = -1;
bool requireWhitespace = false;
if (!SkipWhitespace ())
requireWhitespace = true;
peekChar = PeekChar ();
- if (endsWithQuestion) {
+ if (isXmlDecl) {
if (peekChar == '?')
break;
}
Expect (';');
int predefined = XmlChar.GetPredefinedEntity (entName);
if (predefined < 0) {
- DTDEntityDeclaration entDecl =
- DTD == null ? null : DTD.EntityDecls [entName];
- if (DTD != null && resolver != null && entDecl == null)
- throw new XmlException (this as IXmlLineInfo, "Entity declaration does not exist.");
- if (entDecl != null && entDecl.HasExternalReference)
- throw new XmlException (this as IXmlLineInfo,
- "Reference to external entities is not allowed in the value of an attribute.");
- if (isStandalone && !entDecl.IsInternalSubset)
- throw new XmlException (this as IXmlLineInfo,
- "Reference to external entities is not allowed in the value of an attribute.");
- if (entDecl != null && entDecl.EntityValue.IndexOf ('<') >= 0)
- throw new XmlException (this as IXmlLineInfo,
- "Attribute must not contain character '<' either directly or indirectly by way of entity references.");
+ CheckAttributeEntityReferenceWFC (entName);
currentAttributeValueToken.Value = CreateValueString ();
currentAttributeValueToken.NodeType = XmlNodeType.Text;
if (!isNewToken)
}
+ private void CheckAttributeEntityReferenceWFC (string entName)
+ {
+ DTDEntityDeclaration entDecl =
+ DTD == null ? null : DTD.EntityDecls [entName];
+ if (DTD != null && resolver != null && entDecl == null)
+ throw new XmlException (this, "Referenced entity does not exist.");
+
+ if (entDecl == null)
+ return;
+
+ if (entDecl.HasExternalReference)
+ throw new XmlException (this, "Reference to external entities is not allowed in the value of an attribute.");
+ if (isStandalone && !entDecl.IsInternalSubset)
+ throw new XmlException (this, "Reference to external entities is not allowed in the internal subset.");
+ if (entDecl.EntityValue.IndexOf ('<') >= 0)
+ throw new XmlException (this, "Attribute must not contain character '<' either directly or indirectly by way of entity references.");
+ }
+
// The reader is positioned on the first character
// of the target.
//