{
#region Constructors
- internal XmlDocumentNavigator(XmlNode node)
+ internal XmlDocumentNavigator (XmlNode node)
+ : this (node, null)
+ {
+ nsNodeXml = document.CreateAttribute ("xmlns", "xml", Xmlns);
+ nsNodeXml.Value = XmlnsXML;
+ if (node.NodeType == XmlNodeType.Attribute && node.NamespaceURI == XmlNamespaceManager.XmlnsXmlns) {
+ nsNode = (XmlAttribute) node;
+ node = nsNode.OwnerElement;
+ }
+ }
+
+ private XmlDocumentNavigator (XmlNode node, XmlAttribute nsNodeXml)
{
this.node = node;
this.document = node.NodeType == XmlNodeType.Document ?
node as XmlDocument : node.OwnerDocument;
+ this.nsNodeXml = nsNodeXml;
}
#endregion
private const string Xmlns = "http://www.w3.org/2000/xmlns/";
private const string XmlnsXML = "http://www.w3.org/XML/1998/namespace";
+ private XmlAttribute nsNodeXml;
private XmlNode node;
private XmlDocument document;
// Current namespace node (ancestor's attribute of current node).
- private XmlNode nsNode;
+ private XmlAttribute nsNode;
+ private ArrayList iteratedNsNames = new ArrayList ();
#endregion
public override bool HasAttributes {
get {
- if (nsNode != null)
+ if (NsNode != null)
return false;
if (node.Attributes != null)
- foreach (XmlAttribute attribute in node.Attributes)
- if (attribute.NamespaceURI != Xmlns)
+ for (int i = 0; i < node.Attributes.Count; i++)
+ if (node.Attributes [i].NamespaceURI != Xmlns)
return true;
return false;
}
public override bool HasChildren {
get {
- if (nsNode != null)
+ if (NsNode != null)
return false;
XPathNodeType nodeType = NodeType;
public override bool IsEmptyElement {
get {
- if (nsNode != null)
+ if (NsNode != null)
return false;
return node.NodeType == XmlNodeType.Element
}
}
+ public XmlAttribute NsNode {
+ get { return nsNode; }
+ set {
+ if (value == null)
+ iteratedNsNames.Clear ();
+ else
+ iteratedNsNames.Add (value.Name);
+ nsNode = value;
+ }
+ }
+
public override string LocalName {
get {
+ XmlAttribute nsNode = NsNode;
if (nsNode != null) {
- if (nsNode == document)
+ if (nsNode == nsNodeXml)
return "xml";
else
return (nsNode.Name == "xmlns") ? String.Empty : nsNode.LocalName;
public override string Name {
get {
- if (nsNode != null)
+ if (NsNode != null)
return LocalName;
XPathNodeType nodeType = NodeType;
}
public override string NamespaceURI {
- get { return (nsNode != null) ? String.Empty : node.NamespaceURI; }
+ get { return (NsNode != null) ? String.Empty : node.NamespaceURI; }
}
public override XmlNameTable NameTable {
}
public override XPathNodeType NodeType {
- get { return (nsNode != null) ? XPathNodeType.Namespace : node.XPathNodeType; }
+ get { return (NsNode != null) ? XPathNodeType.Namespace : node.XPathNodeType; }
}
public override string Prefix {
- get { return (nsNode != null) ? String.Empty : node.Prefix; }
+ get { return (NsNode != null) ? String.Empty : node.Prefix; }
}
public override string Value {
case XPathNodeType.Attribute:
case XPathNodeType.Comment:
case XPathNodeType.ProcessingInstruction:
+ return node.Value;
case XPathNodeType.Text:
case XPathNodeType.Whitespace:
case XPathNodeType.SignificantWhitespace:
- return node.Value;
+ string value = node.Value;
+ for (XmlNode n = node.NextSibling; n != null; n = n.NextSibling) {
+ switch (n.XPathNodeType) {
+ case XPathNodeType.Text:
+ case XPathNodeType.Whitespace:
+ case XPathNodeType.SignificantWhitespace:
+ value += n.Value;
+ continue;
+ }
+ break;
+ }
+ return value;
case XPathNodeType.Element:
case XPathNodeType.Root:
return node.InnerText;
case XPathNodeType.Namespace:
- return nsNode == document ? XmlnsXML : nsNode.Value;
+ return NsNode == nsNodeXml ? XmlnsXML : NsNode.Value;
}
return String.Empty;
}
#region Methods
+ private bool CheckNsNameAppearance (string name, string ns)
+ {
+ if (iteratedNsNames.Contains (name))
+ return true;
+ // default namespace erasure - just add name and never return this node
+ if (ns == String.Empty) {
+ iteratedNsNames.Add ("xmlns");
+ return true;
+ }
+
+ return false;
+ }
+
public override XPathNavigator Clone ()
{
- XmlDocumentNavigator clone = new XmlDocumentNavigator (node);
+ XmlDocumentNavigator clone = new XmlDocumentNavigator (node, nsNodeXml);
clone.nsNode = nsNode;
+ clone.iteratedNsNames = (ArrayList) iteratedNsNames.Clone ();
return clone;
}
XmlDocumentNavigator otherDocumentNavigator = other as XmlDocumentNavigator;
if (otherDocumentNavigator != null)
return node == otherDocumentNavigator.node
- && nsNode == otherDocumentNavigator.nsNode;
+ && NsNode == otherDocumentNavigator.NsNode;
return false;
}
if (otherDocumentNavigator != null) {
if (document == otherDocumentNavigator.document) {
node = otherDocumentNavigator.node;
- nsNode = otherDocumentNavigator.nsNode;
+ NsNode = otherDocumentNavigator.NsNode;
return true;
}
}
public override bool MoveToAttribute (string localName, string namespaceURI)
{
if (node.Attributes != null) {
- foreach (XmlAttribute attr in node.Attributes) {
+ for (int i = 0; i < node.Attributes.Count; i++) {
+ XmlAttribute attr = node.Attributes [i];
if (attr.LocalName == localName
&& attr.NamespaceURI == namespaceURI) {
node = attr;
- nsNode = null;
+ NsNode = null;
return true;
}
}
public override bool MoveToFirst ()
{
- if (nsNode == null && node.NodeType != XmlNodeType.Attribute && node.ParentNode != null) {
- MoveToParent ();
+ if (NsNode == null && node.NodeType != XmlNodeType.Attribute && node.ParentNode != null) {
+ if (!MoveToParent ())
+ return false;
// Follow these 2 steps so that we can skip
// some types of nodes .
MoveToFirstChild ();
if (node.Attributes == null)
return false;
if (NodeType == XPathNodeType.Element) {
- foreach (XmlAttribute attr in node.Attributes) {
+ for (int i = 0; i < node.Attributes.Count; i++) {
+ XmlAttribute attr = node.Attributes [i];
if (attr.NamespaceURI != Xmlns) {
node = attr;
- nsNode = null;
+ NsNode = null;
return true;
}
}
XmlElement el = node as XmlElement;
if (node.Attributes != null) {
do {
- foreach (XmlAttribute attr in el.Attributes) {
+ for (int i = 0; i < el.Attributes.Count; i++) {
+ XmlAttribute attr = el.Attributes [i];
if (attr.NamespaceURI == Xmlns) {
- nsNode = attr;
+ if (CheckNsNameAppearance (attr.Name, attr.Value))
+ continue;
+ NsNode = attr;
return true;
}
}
}
if (namespaceScope == XPathNamespaceScope.All) {
- nsNode = document;
+ if (CheckNsNameAppearance (nsNodeXml.Name, nsNodeXml.Value))
+ return false;
+ NsNode = nsNodeXml;
return true;
}
else
public override bool MoveToNamespace (string name)
{
if (name == "xml") {
- nsNode = document;
+ NsNode = nsNodeXml;
return true;
}
XmlElement el = node as XmlElement;
if (node.Attributes != null) {
do {
- foreach (XmlAttribute attr in el.Attributes) {
- if (attr.NamespaceURI == Xmlns && Name == name) {
- nsNode = attr;
+ for (int i = 0; i < el.Attributes.Count; i++) {
+ XmlAttribute attr = el.Attributes [i];
+ if (attr.NamespaceURI == Xmlns && attr.Name == name) {
+ NsNode = attr;
return true;
}
}
public override bool MoveToNext ()
{
- if (nsNode != null)
+ if (NsNode != null)
return false;
if (node.NextSibling != null) {
for(pos++; pos < count; pos++) {
if (owner.Attributes [pos].NamespaceURI != Xmlns) {
node = owner.Attributes [pos];
- nsNode = null;
+ NsNode = null;
return true;
}
}
public override bool MoveToNextNamespace (XPathNamespaceScope namespaceScope)
{
- if (nsNode == document)
+ if (NsNode == nsNodeXml)
// Current namespace is "xml", so there should be no more namespace nodes.
return false;
- if (nsNode == null)
+ if (NsNode == null)
return false;
// Get current attribute's position.
int pos = 0;
- XmlElement owner = ((XmlAttribute) nsNode).OwnerElement;
+ XmlElement owner = ((XmlAttribute) NsNode).OwnerElement;
if (owner == null)
return false;
int count = owner.Attributes.Count;
for(; pos < count; pos++)
- if (owner.Attributes [pos] == nsNode)
+ if (owner.Attributes [pos] == NsNode)
break;
if (pos == count)
return false; // Where is current attribute? Maybe removed.
// Find next namespace from the same element as current ns node.
for(pos++; pos < count; pos++) {
if (owner.Attributes [pos].NamespaceURI == Xmlns) {
- nsNode = owner.Attributes [pos];
+ XmlAttribute a = owner.Attributes [pos];
+ if (CheckNsNameAppearance (a.Name, a.Value))
+ continue;
+ NsNode = a;
return true;
}
}
return false;
owner = owner.ParentNode as XmlElement;
while (owner != null) {
- foreach (XmlAttribute attr in owner.Attributes) {
+ for (int i = 0; i < owner.Attributes.Count; i++) {
+ XmlAttribute attr = owner.Attributes [i];
if (attr.NamespaceURI == Xmlns) {
- nsNode = attr;
+ if (CheckNsNameAppearance (attr.Name, attr.Value))
+ continue;
+ NsNode = attr;
return true;
}
}
}
if (namespaceScope == XPathNamespaceScope.All) {
- nsNode = document;
+ if (CheckNsNameAppearance (nsNodeXml.Name, nsNodeXml.Value))
+ return false;
+ NsNode = nsNodeXml;
return true;
}
- else
- return false;
+ return false;
}
public override bool MoveToParent ()
{
- if (nsNode != null) {
- nsNode = null;
+ if (NsNode != null) {
+ NsNode = null;
return true;
}
else if (node.NodeType == XmlNodeType.Attribute) {
XmlElement ownerElement = ((XmlAttribute)node).OwnerElement;
if (ownerElement != null) {
node = ownerElement;
- nsNode = null;
+ NsNode = null;
return true;
}
} else if (node.ParentNode != null) {
node = node.ParentNode;
- nsNode = null;
+ NsNode = null;
return true;
}
return false;
public override bool MoveToPrevious ()
{
- if (nsNode != null)
+ if (NsNode != null)
return false;
if (node.PreviousSibling != null) {
while (tmp.ParentNode != null)
tmp = tmp.ParentNode;
node = tmp;
- nsNode = null;
+ NsNode = null;
}
- internal XmlNode Node { get { return node; } }
+ internal XmlNode Node { get { return NsNode != null ? NsNode : node; } }
XmlNode IHasXmlNode.GetNode ()
{