Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/DTMXPathNavigator.cs')
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath/DTMXPathNavigator.cs630
1 files changed, 630 insertions, 0 deletions
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/DTMXPathNavigator.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/DTMXPathNavigator.cs
new file mode 100755
index 00000000000..6bd8a339a0e
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/DTMXPathNavigator.cs
@@ -0,0 +1,630 @@
+//
+// Mono.Xml.XPath.DTMXPathNavigator
+//
+// Author:
+// Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
+//
+// (C) 2003 Atsushi Enomoto
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath
+{
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+ class DTMXPathNavigator : XPathNavigator, IXmlLineInfo
+ {
+
+#region Copy of XPathDocument
+ public DTMXPathNavigator (DTMXPathDocument document,
+ XmlNameTable nameTable,
+ DTMXPathLinkedNode [] nodes,
+ DTMXPathAttributeNode [] attributes,
+ DTMXPathNamespaceNode [] namespaces,
+ Hashtable idTable)
+ {
+ this.nodes = nodes;
+ this.attributes = attributes;
+ this.namespaces = namespaces;
+ this.idTable = idTable;
+ this.nameTable = nameTable;
+
+ this.MoveToRoot ();
+ this.document = document;
+ }
+
+ // Copy constructor including position informations.
+ public DTMXPathNavigator (DTMXPathNavigator org)
+ : this (org.document, org.nameTable,
+ org.nodes, org.attributes, org.namespaces,
+ org.idTable)
+ {
+ currentIsNode = org.currentIsNode;
+ currentIsAttr = org.currentIsAttr;
+
+ currentNode = org.currentNode;
+ currentAttr = org.currentAttr;
+ currentNs = org.currentNs;
+ }
+
+ XmlNameTable nameTable;
+
+ // Created XPathDocument. This is used to identify the origin of the navigator.
+ DTMXPathDocument document;
+
+ DTMXPathLinkedNode [] nodes;// = new DTMXPathLinkedNode [0];
+ DTMXPathAttributeNode [] attributes;// = new DTMXPathAttributeNode [0];
+ DTMXPathNamespaceNode [] namespaces;// = new DTMXPathNamespaceNode [0];
+
+ // ID table
+ Hashtable idTable;
+
+// // Key table (considered xsd:keyref for XPath 2.0)
+// Hashtable keyRefTable; // [string key-name] -> idTable
+// // idTable [string value] -> int nodeId
+#endregion
+
+ bool currentIsNode;
+ bool currentIsAttr;
+
+ int currentNode;
+ int currentAttr;
+ int currentNs;
+
+ StringBuilder valueBuilder;
+
+#region Ctor
+
+ internal DTMXPathNavigator (XmlNameTable nt)
+ {
+ this.nameTable = nt;
+ }
+
+#endregion
+
+#region Properties
+
+ public override string BaseURI {
+ get { return nodes [currentNode].BaseURI; }
+ }
+
+ public override bool HasAttributes {
+ get { return currentIsNode ? nodes [currentNode].FirstAttribute != 0 : false; }
+ }
+
+ public override bool HasChildren {
+ get { return currentIsNode ? nodes [currentNode].FirstChild != 0 : false; }
+ }
+
+ public override bool IsEmptyElement {
+ get { return currentIsNode ? nodes [currentNode].IsEmptyElement : false; }
+ }
+
+ int IXmlLineInfo.LineNumber {
+ get {
+ return currentIsAttr ? attributes [currentAttr].LineNumber :
+ nodes [currentNode].LineNumber;
+ }
+ }
+
+ int IXmlLineInfo.LinePosition {
+ get {
+ return currentIsAttr ? attributes [currentAttr].LinePosition :
+ nodes [currentNode].LinePosition;
+ }
+ }
+
+ public override string LocalName {
+ get {
+ if (currentIsNode)
+ return nodes [currentNode].LocalName;
+ else if (currentIsAttr)
+ return attributes [currentAttr].LocalName;
+ else
+ return namespaces [currentNs].Name;
+ }
+ }
+
+ // It maybe scarcely used, so I decided to compute it always.
+ public override string Name {
+ get {
+ string prefix;
+ string localName;
+ if (currentIsNode) {
+ prefix = nodes [currentNode].Prefix;
+ localName = nodes [currentNode].LocalName;
+ } else if (currentIsAttr) {
+ prefix = attributes [currentAttr].Prefix;
+ localName = attributes [currentAttr].LocalName;
+ } else
+ return namespaces [currentNs].Name;
+
+ if (prefix != "")
+ return prefix + ':' + localName;
+ else
+ return localName;
+ }
+ }
+
+ public override string NamespaceURI {
+ get {
+ if (currentIsNode)
+ return nodes [currentNode].NamespaceURI;
+ if (currentIsAttr)
+ return attributes [currentAttr].NamespaceURI;
+ return String.Empty;
+ }
+ }
+
+ public override XmlNameTable NameTable {
+ get { return nameTable; }
+ }
+
+ public override XPathNodeType NodeType {
+ get {
+ if (currentIsNode)
+ return nodes [currentNode].NodeType;
+ else if (currentIsAttr)
+ return XPathNodeType.Attribute;
+ else
+ return XPathNodeType.Namespace;
+ }
+ }
+
+ public override string Prefix {
+ get {
+ if (currentIsNode)
+ return nodes [currentNode].Prefix;
+ else if (currentIsAttr)
+ return attributes [currentAttr].Prefix;
+ return String.Empty;
+ }
+ }
+
+ public override string Value {
+ get {
+ if (currentIsAttr)
+ return attributes [currentAttr].Value;
+ else if (!currentIsNode)
+ return namespaces [currentNs].Namespace;
+
+ switch (nodes [currentNode].NodeType) {
+ case XPathNodeType.Comment:
+ case XPathNodeType.ProcessingInstruction:
+ case XPathNodeType.Text:
+ case XPathNodeType.Whitespace:
+ case XPathNodeType.SignificantWhitespace:
+ return nodes [currentNode].Value;
+ }
+
+ // Element
+ if (valueBuilder == null)
+ valueBuilder = new StringBuilder ();
+ else
+ valueBuilder.Length = 0;
+
+ int iter = nodes [currentNode].FirstChild;
+ int depth = nodes [currentNode].Depth;
+ while (iter < nodes.Length && nodes [iter].Depth > depth) {
+ switch (nodes [iter].NodeType) {
+ case XPathNodeType.Comment:
+ case XPathNodeType.ProcessingInstruction:
+ break;
+ default:
+ valueBuilder.Append (nodes [iter].Value);
+ break;
+ }
+ iter++;
+ }
+
+ return valueBuilder.ToString ();
+ }
+ }
+
+ public override string XmlLang {
+ get { return nodes [currentNode].XmlLang; }
+ }
+
+#endregion
+
+#region Methods
+
+ public override XPathNavigator Clone ()
+ {
+ return new DTMXPathNavigator (this);
+ }
+
+ public override XmlNodeOrder ComparePosition (XPathNavigator nav)
+ {
+ DTMXPathNavigator another = nav as DTMXPathNavigator;
+
+ if (another == null || another.document != this.document)
+ return XmlNodeOrder.Unknown;
+
+ if (currentNode > another.currentNode)
+ return XmlNodeOrder.After;
+ else if (currentNode < another.currentNode)
+ return XmlNodeOrder.Before;
+
+ // another may attr or ns,
+ // and this may be also attr or ns.
+ if (another.currentIsAttr) {
+ if (this.currentIsAttr) {
+ if (currentAttr > another.currentAttr)
+ return XmlNodeOrder.After;
+ else if (currentAttr < another.currentAttr)
+ return XmlNodeOrder.Before;
+ else
+ return XmlNodeOrder.Same;
+ } else
+ return XmlNodeOrder.Before;
+ } else if (!another.currentIsNode) {
+ if (!this.currentIsNode) {
+ if (currentNs > another.currentNs)
+ return XmlNodeOrder.After;
+ else if (currentNs < another.currentNs)
+ return XmlNodeOrder.Before;
+ else
+ return XmlNodeOrder.Same;
+ } else
+ return XmlNodeOrder.Before;
+ } else
+ return !another.currentIsNode ? XmlNodeOrder.Before : XmlNodeOrder.Same;
+ }
+
+ private int findAttribute (string localName, string namespaceURI)
+ {
+ if (currentIsNode && nodes [currentNode].NodeType == XPathNodeType.Element) {
+ int cur = nodes [currentNode].FirstAttribute;
+ while (cur != 0) {
+ if (attributes [cur].LocalName == localName && attributes [cur].NamespaceURI == namespaceURI)
+ return cur;
+ cur = attributes [cur].NextAttribute;
+ }
+ }
+ return 0;
+ }
+
+ public override string GetAttribute (string localName,
+ string namespaceURI)
+ {
+ int attr = findAttribute (localName, namespaceURI);
+ return (attr != 0) ? attributes [attr].Value : String.Empty;
+ }
+
+ public override string GetNamespace (string name)
+ {
+ if (currentIsNode && nodes [currentNode].NodeType == XPathNodeType.Element) {
+ int nsNode = nodes [currentNode].FirstNamespace;
+ while (nsNode != 0) {
+ if (namespaces [nsNode].Name == name)
+ return namespaces [nsNode].Namespace;
+ nsNode = namespaces [nsNode].NextNamespace;
+ }
+ }
+ return String.Empty;
+ }
+
+ bool IXmlLineInfo.HasLineInfo ()
+ {
+ return true;
+ }
+
+ public override bool IsDescendant (XPathNavigator nav)
+ {
+ DTMXPathNavigator another = nav as DTMXPathNavigator;
+
+ if (another == null || another.document != this.document)
+ return false;
+
+ // Maybe we can improve here more efficiently by
+ // comparing node indices.
+ if (another.currentNode == currentNode)
+ return !another.currentIsNode;
+ int tmp = nodes [another.currentNode].Parent;
+ while (tmp != 0) {
+ if (tmp == currentNode)
+ return true;
+ tmp = nodes [tmp].Parent;
+ }
+ return false;
+ }
+
+ public override bool IsSamePosition (XPathNavigator other)
+ {
+ DTMXPathNavigator another = other as DTMXPathNavigator;
+
+ if (another == null || another.document != this.document)
+ return false;
+
+ if (this.currentNode != another.currentNode ||
+ this.currentIsAttr != another.currentIsAttr ||
+ this.currentIsNode != another.currentIsNode)
+ return false;
+
+ if (currentIsAttr)
+ return this.currentAttr == another.currentAttr;
+ else if (!currentIsNode)
+ return this.currentNs == another.currentNs;
+ return true;
+ }
+
+ public override bool MoveTo (XPathNavigator other)
+ {
+ DTMXPathNavigator another = other as DTMXPathNavigator;
+
+ if (another == null || another.document != this.document)
+ return false;
+
+ this.currentNode = another.currentNode;
+ this.currentAttr = another.currentAttr;
+ this.currentNs = another.currentNs;
+ this.currentIsNode = another.currentIsNode;
+ this.currentIsAttr = another.currentIsAttr;
+ return true;
+ }
+
+ public override bool MoveToAttribute (string localName,
+ string namespaceURI)
+ {
+ int attr = findAttribute (localName, namespaceURI);
+ if (attr == 0)
+ return false;
+
+ currentAttr = attr;
+ currentIsAttr = true;
+ currentIsNode = false;
+ return true;
+ }
+
+ public override bool MoveToFirst ()
+ {
+ if (currentIsAttr)
+ return false;
+
+ int cur = nodes [currentNode].PreviousSibling;
+ if (cur == 0)
+ return false;
+
+ int next = cur;
+ while (next != 0) {
+ cur = next;
+ next = nodes [cur].PreviousSibling;
+ }
+ currentNode = cur;
+ currentIsNode = true;
+ return true;
+ }
+
+ public override bool MoveToFirstAttribute ()
+ {
+ if (!currentIsNode)
+ return false;
+
+ int first = nodes [currentNode].FirstAttribute;
+ if (first == 0)
+ return false;
+
+ currentAttr = first;
+ currentIsAttr = true;
+ currentIsNode = false;
+ return true;
+ }
+
+ public override bool MoveToFirstChild ()
+ {
+ if (!currentIsNode)
+ return false;
+
+ int first = nodes [currentNode].FirstChild;
+ if (first == 0)
+ return false;
+
+ currentNode = first;
+ return true;
+ }
+
+ private bool moveToSpecifiedNamespace (int cur,
+ XPathNamespaceScope namespaceScope)
+ {
+ if (cur == 0)
+ return false;
+
+ if (namespaceScope == XPathNamespaceScope.Local &&
+ namespaces [cur].DeclaredElement != currentNode)
+ return false;
+
+ if (namespaceScope != XPathNamespaceScope.All
+ && namespaces [cur].Namespace == XmlNamespaces.XML)
+ return false;
+
+ if (cur != 0) {
+ moveToNamespace (cur);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ public override bool MoveToFirstNamespace (
+ XPathNamespaceScope namespaceScope)
+ {
+ if (!currentIsNode)
+ return false;
+ int cur = nodes [currentNode].FirstNamespace;
+ return moveToSpecifiedNamespace (cur, namespaceScope);
+ }
+
+ // Note that this support is extension to XPathDocument.
+ // XPathDocument does not support ID reference.
+ public override bool MoveToId (string id)
+ {
+ if (idTable.ContainsKey (id)) {
+ currentNode = (int) idTable [id];
+ currentIsNode = true;
+ currentIsAttr = false;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ private void moveToNamespace (int nsNode)
+ {
+ currentIsNode = currentIsAttr = false;
+ currentNs = nsNode;
+ }
+
+ public override bool MoveToNamespace (string name)
+ {
+ int cur = nodes [currentNode].FirstNamespace;
+ if (cur == 0)
+ return false;
+
+ while (cur != 0) {
+ if (namespaces [cur].Name == name) {
+ moveToNamespace (cur);
+ return true;
+ }
+ cur = namespaces [cur].NextNamespace;
+ }
+ return false;
+ }
+
+ public override bool MoveToNext ()
+ {
+ if (currentIsAttr)
+ return false;
+
+ int next = nodes [currentNode].NextSibling;
+ if (next == 0)
+ return false;
+ currentNode = next;
+ currentIsNode = true;
+ return true;
+ }
+
+ public override bool MoveToNextAttribute ()
+ {
+ if (!currentIsAttr)
+ return false;
+
+ int next = attributes [currentAttr].NextAttribute;
+ if (next == 0)
+ return false;
+ currentAttr = next;
+ return true;
+ }
+
+ public override bool MoveToNextNamespace (
+ XPathNamespaceScope namespaceScope)
+ {
+ if (currentIsAttr || currentIsNode)
+ return false;
+
+ int cur = namespaces [currentNs].NextNamespace;
+ return moveToSpecifiedNamespace (cur, namespaceScope);
+ }
+
+ public override bool MoveToParent ()
+ {
+ if (!currentIsNode) {
+ currentIsNode = true;
+ currentIsAttr = false;
+ return true;
+ }
+
+ int parent = nodes [currentNode].Parent;
+ if (parent == 0) // It is root itself.
+ return false;
+
+ currentNode = parent;
+ return true;
+ }
+
+ public override bool MoveToPrevious ()
+ {
+ if (currentIsAttr)
+ return false;
+
+ int previous = nodes [currentNode].PreviousSibling;
+ if (previous == 0)
+ return false;
+ currentNode = previous;
+ currentIsNode = true;
+ return true;
+ }
+
+ public override void MoveToRoot ()
+ {
+ currentNode = 1; // root is 1.
+ currentIsNode = true;
+ currentIsAttr = false;
+ }
+
+#endregion
+
+ /*
+ public string DebugDump {
+ get {
+ StringBuilder sb = new StringBuilder ();
+
+ for (int i = 0; i < namespaces.Length; i++) {
+ DTMXPathNamespaceNode n = namespaces [i];
+ sb.AppendFormat ("{0}: {1},{2} {3}/{4}\n", i,
+ n.DeclaredElement, n.NextNamespace,
+ n.Name, n.Namespace);
+ }
+
+ for (int i=0; i<this.nodes.Length; i++) {
+ DTMXPathLinkedNode n = nodes [i];
+ sb.AppendFormat ("{0}: {1}:{2} {3} {4} {5} {6} {7}\n", new object [] {i, n.Prefix, n.LocalName, n.NamespaceURI, n.FirstNamespace, n.FirstAttribute, n.FirstChild, n.Parent});
+ }
+
+ for (int i=0; i<this.attributes.Length; i++) {
+ DTMXPathAttributeNode n = attributes [i];
+ sb.AppendFormat ("{0}: {1}:{2} {3} {4}\n", i, n.Prefix, n.LocalName, n.NamespaceURI, n.NextAttribute);
+ }
+
+ return sb.ToString ();
+ }
+ }
+ */
+
+ }
+
+ internal class XmlNamespaces
+ {
+ public const string XML = "http://www.w3.org/XML/1998/namespace";
+ public const string XMLNS = "http://www.w3.org/2000/xmlns/";
+ }
+}