// 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
namespace System.Xml.Linq
{
- internal class XNodeReader : XmlReader
+ internal class XNodeReader : XmlReader, IXmlLineInfo
{
ReadState state = ReadState.Initial;
XNode node, start;
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)
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)
public override bool HasAttributes {
get {
- if (end_element || node == null)
+ if (EOF || end_element || node == null)
return false;
if (node is XElement)
public override bool HasValue {
get {
+ if (EOF)
+ return false;
if (attr >= 0)
return true;
switch (node.NodeType) {
}
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;
// 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);
}
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;
}
}
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 :
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;
}
}
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 ()
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;
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;
}
}
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;
}
return true;
}
- public override bool ReadAttributeValue ()
+ public
+ override
+ bool ReadAttributeValue ()
{
if (attr < 0 || attr_value)
return false;
{
throw new NotSupportedException ();
}
+
+ // Note that this does not return attribute node.
+ internal XNode CurrentNode {
+ get { return node; }
+ }
}
}