Merge pull request #950 from ermshiperete/bug-xamarin-2787
[mono.git] / mcs / class / System.Xml.Linq / System.Xml.Linq / XNodeReader.cs
index 03ec58c4b5e0931ef6464a36596c8daa4abee85a..95631f1bbaaf3121ebc4a6a6d5017a36eba59125 100644 (file)
@@ -3,6 +3,7 @@
 //   Atsushi Enomoto
 //
 // Copyright 2007 Novell (http://www.novell.com)
+// Copyright 2011 Xamarin Inc (http://www.xamarin.com).
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -31,7 +32,7 @@ using XPI = System.Xml.Linq.XProcessingInstruction;
 
 namespace System.Xml.Linq
 {
-       internal class XNodeReader : XmlReader
+       internal class XNodeReader : XmlReader, IXmlLineInfo
        {
                ReadState state = ReadState.Initial;
                XNode node, start;
@@ -45,7 +46,29 @@ namespace System.Xml.Linq
                        this.node = node;
                        start = node;
                }
+               
+#if NET_4_0
+               internal bool OmitDuplicateNamespaces { get; set; }
+#endif
 
+               int IXmlLineInfo.LineNumber {
+                       get {
+                               var o = (XObject) GetCurrentAttribute () ?? node;
+                               return o != null ? o.LineNumber : 0;
+                       }
+               }
+               int IXmlLineInfo.LinePosition {
+                       get {
+                               var o = (XObject) GetCurrentAttribute () ?? node;
+                               return o != null ? o.LinePosition : 0;
+                       }
+               }
+               bool IXmlLineInfo.HasLineInfo ()
+               {
+                               var o = (XObject) GetCurrentAttribute () ?? node;
+                               return o != null ? ((IXmlLineInfo) o).HasLineInfo () : false;
+               }
+       
                public override int AttributeCount {
                        get {
                                if (state != ReadState.Interactive || end_element)
@@ -80,6 +103,8 @@ namespace System.Xml.Linq
 
                public override int Depth {
                        get {
+                               if (EOF)
+                                       return 0;
                                int i = 0;
                                // document.Depth = 0, root.Depth = 0, others.Depth = they depend
                                for (XNode n = node.Parent; n != null; n = n.Parent)
@@ -98,7 +123,7 @@ namespace System.Xml.Linq
 
                public override bool HasAttributes {
                        get {
-                               if (end_element || node == null)
+                               if (EOF || end_element || node == null)
                                        return false;
 
                                if (node is XElement)
@@ -109,6 +134,8 @@ namespace System.Xml.Linq
 
                public override bool HasValue {
                        get {
+                               if (EOF)
+                                       return false;
                                if (attr >= 0)
                                        return true;
                                switch (node.NodeType) {
@@ -123,16 +150,18 @@ namespace System.Xml.Linq
                }
 
                public override bool IsEmptyElement {
-                       get { return node is XElement ? ((XElement) node).IsEmpty : false; }
+                       get { return !EOF && attr < 0 && node is XElement ? ((XElement) node).IsEmpty : false; }
                }
 
-               XAttribute GetCurrentAttribute ()
+               internal XAttribute GetCurrentAttribute ()
                {
                        return GetXAttribute (attr);
                }
 
                XAttribute GetXAttribute (int idx)
                {
+                       if (EOF)
+                               return null;
                        XElement el = node as XElement;
                        if (el == null)
                                return null;
@@ -146,7 +175,7 @@ namespace System.Xml.Linq
                // XName for element and attribute, string for xmldecl attributes, doctype attribute, doctype name and PI, null for empty.
                object GetCurrentName ()
                {
-                       if (attr_value)
+                       if (EOF || attr_value)
                                return null;
                        return GetName (attr);
                }
@@ -200,9 +229,12 @@ namespace System.Xml.Linq
 
                public override string NamespaceURI {
                        get {
-                               object name = GetCurrentName ();
-                               if (name is XName)
-                                       return ((XName) name).NamespaceName;
+                               XName name = GetCurrentName () as XName;
+                               if (name != null)
+                                       // XName for "xmlns" has NamespaceName as "", so we have to return w3c xmlns as a special case.
+                                       return name.LocalName == "xmlns" && name.Namespace == XNamespace.None ?
+                                               XNamespace.Xmlns.NamespaceName :
+                                               name.NamespaceName;
                                return String.Empty;
                        }
                }
@@ -213,7 +245,8 @@ namespace System.Xml.Linq
 
                public override XmlNodeType NodeType {
                        get {
-                               return  end_element ? XmlNodeType.EndElement :
+                               return  state != ReadState.Interactive ? XmlNodeType.None :
+                                       end_element ? XmlNodeType.EndElement :
                                        attr_value ? XmlNodeType.Text :
                                        attr >= 0 ? XmlNodeType.Attribute :
                                        node.NodeType == XmlNodeType.Document ? XmlNodeType.XmlDeclaration :
@@ -229,7 +262,7 @@ namespace System.Xml.Linq
                                XElement el = (node as XElement) ?? node.Parent;
                                if (el == null)
                                        return String.Empty;
-                               return el.GetPrefixOfNamespace (name.Namespace);
+                               return el.GetPrefixOfNamespace (name.Namespace) ?? String.Empty;
                        }
                }
 
@@ -289,10 +322,13 @@ namespace System.Xml.Linq
 
                public override string LookupNamespace (string prefix)
                {
+                       if (EOF)
+                               return null;
                        XElement el = (node as XElement) ?? node.Parent;
                        if (el == null)
-                               return String.Empty;
-                       return el.GetNamespaceOfPrefix (prefix).NamespaceName;
+                               return null;
+                       var xn = el.GetNamespaceOfPrefix (prefix);
+                       return xn != XNamespace.None ? xn.NamespaceName : null;
                }
 
                public override bool MoveToElement ()
@@ -430,12 +466,20 @@ namespace System.Xml.Linq
 
                public override bool Read ()
                {
+                       // clear attribute state on element/xmldecl/dtd.
+                       attr = -1;
+                       attr_value = false;
+
                        switch (state) {
                        case ReadState.Initial:
                                state = ReadState.Interactive;
                                XDocument doc = node as XDocument;
-                               if (doc != null && doc.Declaration != null)
-                                       return true;
+                               if (doc != null) {
+                                       if (doc.Declaration != null)
+                                               return true;
+                               }
+                               else
+                                       return true; // any other root
                                break;
                        case ReadState.Interactive:
                                break;
@@ -443,10 +487,6 @@ namespace System.Xml.Linq
                                return false;
                        }
 
-                       // clear attribute state on element/xmldecl/dtd.
-                       attr = -1;
-                       attr_value = false;
-
                        // when positioned on xmldecl, move to children
                        if (node is XDocument) {
                                XDocument doc = node as XDocument;
@@ -471,11 +511,11 @@ namespace System.Xml.Linq
                                }
                        }
                        end_element = false;
-                       if (node.NextNode != null) {
+                       if (node.NextNode != null && node != start) {
                                node = node.NextNode;
                                return true;
                        }
-                       if (node.Parent == null || end_element && node == start) {
+                       if (node.Parent == null || node == start) {
                                state = ReadState.EndOfFile;
                                return false;
                        }
@@ -484,7 +524,9 @@ namespace System.Xml.Linq
                        return true;
                }
 
-               public override bool ReadAttributeValue ()
+               public
+               override
+               bool ReadAttributeValue ()
                {
                        if (attr < 0 || attr_value)
                                return false;
@@ -496,5 +538,10 @@ namespace System.Xml.Linq
                {
                        throw new NotSupportedException ();
                }
+               
+               // Note that this does not return attribute node.
+               internal XNode CurrentNode {
+                       get { return node; }
+               }
        }
 }