| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713 |
- //
- // Mono.Xml.XPath.DTMXPathNavigator2
- //
- // Author:
- // Atsushi Enomoto <[email protected]>
- //
- // (C) 2004 Novell Inc.
- //
- //
- // 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;
- using System.ServiceModel.Dispatcher;
- namespace Mono.Xml.XPath
- {
- #if OUTSIDE_SYSTEM_XML
- public
- #else
- internal
- #endif
- class SeekableDTMXPathNavigator2 : SeekableXPathNavigator, IXmlLineInfo
- {
- public SeekableDTMXPathNavigator2 (DTMXPathDocument2 document)
- {
- this.MoveToRoot ();
- this.document = document;
- }
- // Copy constructor including position informations.
- public SeekableDTMXPathNavigator2 (SeekableDTMXPathNavigator2 org)
- {
- document = org.document;
- currentIsNode = org.currentIsNode;
- currentIsAttr = org.currentIsAttr;
- currentNode = org.currentNode;
- currentAttr = org.currentAttr;
- currentNs = org.currentNs;
- }
- #region SeekableXPathNavigator members
- public override long CurrentPosition {
- get { return currentIsNode ? currentNode : currentIsAttr ? nodes.Length + currentAttr : nodes.Length + attributes.Length + currentNs; }
- set {
- int pos = (int) value;
- if (pos < nodes.Length) {
- currentIsAttr = false;
- currentIsNode = true;
- currentNode = pos;
- } else if (pos < nodes.Length + attributes.Length) {
- currentIsAttr = true;
- currentIsNode = false;
- currentAttr = pos - nodes.Length;
- } else if (pos < nodes.Length + attributes.Length + namespaces.Length) {
- currentIsAttr = false;
- currentIsNode = false;
- currentNs = pos - nodes.Length - attributes.Length;
- } else
- throw new ArgumentOutOfRangeException ();
- }
- }
- public override XPathNodeType GetNodeType (long nodePosition)
- {
- return
- nodePosition < nodes.Length ? nodes [nodePosition].NodeType :
- nodePosition < nodes.Length + attributes.Length ? XPathNodeType.Attribute :
- XPathNodeType.Namespace;
- }
- public override string GetLocalName (long nodePosition)
- {
- switch (GetNodeType (nodePosition)) {
- case XPathNodeType.Namespace:
- return atomicStringPool [namespaces [nodePosition - nodes.Length - attributes.Length].Name];
- case XPathNodeType.Attribute:
- return atomicStringPool [attributes [nodePosition - nodes.Length].LocalName];
- default:
- return atomicStringPool [nodes [nodePosition].LocalName];
- }
- }
- public override string GetName (long nodePosition)
- {
- switch (GetNodeType (nodePosition)) {
- case XPathNodeType.Namespace:
- return atomicStringPool [namespaces [nodePosition - nodes.Length - attributes.Length].Name];
- case XPathNodeType.Attribute:
- return atomicStringPool [attributes [nodePosition - nodes.Length].LocalName];
- default:
- return atomicStringPool [nodes [nodePosition].LocalName];
- }
- }
- public override string GetNamespace (long nodePosition)
- {
- switch (GetNodeType (nodePosition)) {
- case XPathNodeType.Namespace:
- return atomicStringPool [namespaces [nodePosition - nodes.Length - attributes.Length].Namespace];
- case XPathNodeType.Attribute:
- return atomicStringPool [attributes [nodePosition - nodes.Length].NamespaceURI];
- default:
- return atomicStringPool [nodes [nodePosition].NamespaceURI];
- }
- }
- public override string GetValue (long nodePosition)
- {
- switch (GetNodeType (nodePosition)) {
- case XPathNodeType.Namespace:
- return atomicStringPool [namespaces [nodePosition - nodes.Length - attributes.Length].Namespace];
- case XPathNodeType.Attribute:
- return nonAtomicStringPool [attributes [nodePosition - nodes.Length].Value];
- default:
- return nonAtomicStringPool [nodes [nodePosition].Value];
- }
- }
- int GetOwnerPosition (long position)
- {
- int pos = (int) position;
- return pos < nodes.Length ? pos :
- pos < nodes.Length + attributes.Length ?
- attributes [(int) pos].OwnerElement :
- namespaces [(int) pos].DeclaredElement;
- }
- public override XmlNodeOrder ComparePosition (long firstPosition, long secondPosition)
- {
- if (firstPosition == secondPosition)
- return XmlNodeOrder.Same;
- int link1 = GetOwnerPosition (firstPosition);
- int link2 = GetOwnerPosition (secondPosition);
- if (link1 == link2)
- // on the same element. Comparison could be done numerically.
- return firstPosition < secondPosition ? XmlNodeOrder.Before :
- XmlNodeOrder.After;
- else
- // on different linked nodes.
- return link1 < link2 ?
- XmlNodeOrder.Before :
- XmlNodeOrder.After;
- }
- #endregion
- XmlNameTable nameTable {
- get { return document.NameTable; }
- }
- // Created XPathDocument. This is used to identify the origin of the navigator.
- DTMXPathDocument2 document;
- DTMXPathLinkedNode2 [] nodes {
- get { return document.Nodes; }
- }
- DTMXPathAttributeNode2 [] attributes {
- get { return document.Attributes; }
- }
- DTMXPathNamespaceNode2 [] namespaces {
- get { return document.Namespaces; }
- }
- string [] atomicStringPool {
- get { return document.AtomicStringPool; }
- }
- string [] nonAtomicStringPool {
- get { return document.NonAtomicStringPool; }
- }
- // ID table
- Hashtable idTable {
- get { return document.IdTable; }
- }
- bool currentIsNode;
- bool currentIsAttr;
- int currentNode;
- int currentAttr;
- int currentNs;
- #region Properties
- public override string BaseURI {
- get { return atomicStringPool [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 atomicStringPool [nodes [currentNode].LocalName];
- else if (currentIsAttr)
- return atomicStringPool [attributes [currentAttr].LocalName];
- else
- return atomicStringPool [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 = atomicStringPool [nodes [currentNode].Prefix];
- localName = atomicStringPool [nodes [currentNode].LocalName];
- } else if (currentIsAttr) {
- prefix = atomicStringPool [attributes [currentAttr].Prefix];
- localName = atomicStringPool [attributes [currentAttr].LocalName];
- } else
- return atomicStringPool [namespaces [currentNs].Name];
- if (prefix != "")
- return prefix + ':' + localName;
- else
- return localName;
- }
- }
- public override string NamespaceURI {
- get {
- if (currentIsNode)
- return atomicStringPool [nodes [currentNode].NamespaceURI];
- if (currentIsAttr)
- return atomicStringPool [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 atomicStringPool [nodes [currentNode].Prefix];
- else if (currentIsAttr)
- return atomicStringPool [attributes [currentAttr].Prefix];
- return String.Empty;
- }
- }
- public override string Value {
- get {
- if (currentIsAttr)
- return nonAtomicStringPool [attributes [currentAttr].Value];
- else if (!currentIsNode)
- return atomicStringPool [namespaces [currentNs].Namespace];
-
- switch (nodes [currentNode].NodeType) {
- case XPathNodeType.Comment:
- case XPathNodeType.ProcessingInstruction:
- case XPathNodeType.Text:
- case XPathNodeType.Whitespace:
- case XPathNodeType.SignificantWhitespace:
- return nonAtomicStringPool [nodes [currentNode].Value];
- }
- // Element - collect all content values
- int iter = nodes [currentNode].FirstChild;
- if (iter == 0)
- return String.Empty;
- StringBuilder builder = null;
- BuildValue (iter, ref builder);
- return builder == null ? String.Empty : builder.ToString ();
- }
- }
- void BuildValue (int iter, ref StringBuilder valueBuilder)
- {
- int end = nodes [currentNode].NextSibling;
- if (end == 0) {
- int tmp = currentNode;
- do {
- tmp = nodes [tmp].Parent;
- end = nodes [tmp].NextSibling;
- } while (end == 0 && tmp != 0);
- if (end == 0)
- end = nodes.Length;
- }
- while (iter < end) {
- switch (nodes [iter].NodeType) {
- case XPathNodeType.Text:
- case XPathNodeType.SignificantWhitespace:
- case XPathNodeType.Whitespace:
- if (valueBuilder == null)
- valueBuilder = new StringBuilder ();
- valueBuilder.Append (nonAtomicStringPool [nodes [iter].Value]);
- break;
- }
- iter++;
- }
- }
- public override string XmlLang {
- get { return atomicStringPool [nodes [currentNode].XmlLang]; }
- }
- #endregion
- #region Methods
- public override XPathNavigator Clone ()
- {
- return new SeekableDTMXPathNavigator2 (this);
- }
- public override XmlNodeOrder ComparePosition (XPathNavigator nav)
- {
- SeekableDTMXPathNavigator2 another = nav as SeekableDTMXPathNavigator2;
- 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 (atomicStringPool [attributes [cur].LocalName] == localName && atomicStringPool [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) ? nonAtomicStringPool [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 (atomicStringPool [namespaces [nsNode].Name] == name)
- return atomicStringPool [namespaces [nsNode].Namespace];
- nsNode = namespaces [nsNode].NextNamespace;
- }
- }
- return String.Empty;
- }
- bool IXmlLineInfo.HasLineInfo ()
- {
- return true;
- }
- public override bool IsDescendant (XPathNavigator nav)
- {
- SeekableDTMXPathNavigator2 another = nav as SeekableDTMXPathNavigator2;
- if (another == null || another.document != this.document)
- return false;
- if (another.currentNode == currentNode)
- return !another.currentIsNode;
- int tmp = nodes [another.currentNode].Parent;
- // ancestors must appear in prior on the node list.
- if (tmp < currentNode)
- return false;
- while (tmp != 0) {
- if (tmp == currentNode)
- return true;
- tmp = nodes [tmp].Parent;
- }
- return false;
- }
- public override bool IsSamePosition (XPathNavigator other)
- {
- SeekableDTMXPathNavigator2 another = other as SeekableDTMXPathNavigator2;
- 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)
- {
- SeekableDTMXPathNavigator2 another = other as SeekableDTMXPathNavigator2;
- 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;
- cur = nodes [cur].Parent;
- cur = nodes [cur].FirstChild;
- 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.IndexXML)
- 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 (atomicStringPool [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
- }
- class XmlNamespaces
- {
- public const string XML = "http://www.w3.org/XML/1998/namespace";
- public const string XMLNS = "http://www.w3.org/2000/xmlns/";
- public const int IndexXML = 2;
- public const int IndexXMLNS = 3;
- }
- }
|