5 // Copyright 2007 Novell (http://www.novell.com)
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Xml.Schema;
32 using System.Xml.XPath;
34 using XPI = System.Xml.Linq.XProcessingInstruction;
36 namespace System.Xml.Linq
38 internal class XNodeNavigator : XPathNavigator
40 static readonly XAttribute attr_ns_xml = new XAttribute (XNamespace.Xmlns.GetName ("xml"), XNamespace.Xml.NamespaceName);
44 XmlNameTable name_table;
46 public XNodeNavigator (XNode node, XmlNameTable nameTable)
49 this.name_table = nameTable;
52 public XNodeNavigator (XNodeNavigator other)
54 this.node = other.node;
55 this.attr = other.attr;
56 this.name_table = other.name_table;
59 public override string BaseURI {
60 get { return node.BaseUri ?? String.Empty; }
63 public override bool CanEdit {
67 public override bool HasAttributes {
69 XElement el = node as XElement;
70 return el != null && el.HasAttributes;
74 public override bool HasChildren {
76 XContainer c = node as XContainer;
77 return c != null && c.FirstNode != null;
81 public override bool IsEmptyElement {
83 XElement el = node as XElement;
84 return el != null && el.IsEmpty;
88 public override string LocalName {
91 case XPathNodeType.Namespace:
92 return attr.Name.Namespace == XNamespace.None ? String.Empty : attr.Name.LocalName;
93 case XPathNodeType.Attribute:
94 return attr.Name.LocalName;
95 case XPathNodeType.Element:
96 return ((XElement) node).Name.LocalName;
97 case XPathNodeType.ProcessingInstruction:
98 return ((XPI) node).Target;
105 public override string Name {
109 case XPathNodeType.Attribute:
112 case XPathNodeType.Element:
113 name = ((XElement) node).Name;
118 if (name.Namespace == XNamespace.None)
119 return name.LocalName;
120 XElement el = (node as XElement) ?? node.Parent;
122 return name.LocalName;
123 string prefix = el.GetPrefixOfNamespace (name.Namespace);
124 return prefix.Length > 0 ? String.Concat (prefix, ":", name.LocalName) : name.LocalName;
128 public override string NamespaceURI {
131 case XPathNodeType.Namespace:
133 case XPathNodeType.Attribute:
134 return attr.Name.NamespaceName;
135 case XPathNodeType.Element:
136 return ((XElement) node).Name.NamespaceName;
143 public override XmlNameTable NameTable {
144 get { return name_table; }
147 public override XPathNodeType NodeType {
150 return attr.IsNamespaceDeclaration ?
151 XPathNodeType.Namespace :
152 XPathNodeType.Attribute;
153 switch (node.NodeType) {
154 case XmlNodeType.Element:
155 return XPathNodeType.Element;
156 case XmlNodeType.Document:
157 return XPathNodeType.Root;
158 case XmlNodeType.Comment:
159 return XPathNodeType.Comment;
160 case XmlNodeType.ProcessingInstruction:
161 return XPathNodeType.ProcessingInstruction;
163 return XPathNodeType.Text;
168 public override string Prefix {
172 case XPathNodeType.Attribute:
175 case XPathNodeType.Element:
176 name = ((XElement) node).Name;
181 if (name.Namespace == XNamespace.None)
183 XElement el = (node as XElement) ?? node.Parent;
186 return el.GetPrefixOfNamespace (name.Namespace);
191 public override IXmlSchemaInfo SchemaInfo {
192 get { throw new NotImplementedException (); }
195 public override object UnderlyingObject {
196 get { return attr != null ? (object) attr : node; }
199 public override string Value {
205 case XPathNodeType.Comment:
206 return ((XComment) node).Value;
207 case XPathNodeType.ProcessingInstruction:
208 return ((XPI) node).Data;
209 case XPathNodeType.Text:
210 return ((XText) node).Value;
211 case XPathNodeType.Element:
212 case XPathNodeType.Root:
213 return GetInnerText ((XContainer) node);
219 string GetInnerText (XContainer node)
221 StringBuilder sb = null;
222 foreach (XNode n in node.Nodes ())
223 GetInnerText (n, ref sb);
224 return sb != null ? sb.ToString () : String.Empty;
227 void GetInnerText (XNode n, ref StringBuilder sb)
229 switch (n.NodeType) {
230 case XmlNodeType.Element:
231 foreach (XNode c in ((XElement) n).Nodes ())
232 GetInnerText (c, ref sb);
234 case XmlNodeType.Text:
235 case XmlNodeType.CDATA:
237 sb = new StringBuilder ();
238 sb.Append (((XText) n).Value);
243 public override XPathNavigator Clone ()
245 return new XNodeNavigator (this);
248 public override bool IsSamePosition (XPathNavigator other)
250 XNodeNavigator nav = other as XNodeNavigator;
251 if (nav == null || nav.node.Owner != node.Owner)
253 return node == nav.node && attr == nav.attr;
256 public override bool MoveTo (XPathNavigator other)
258 XNodeNavigator nav = other as XNodeNavigator;
259 if (nav == null || nav.node.Owner != node.Owner)
266 public override bool MoveToFirstAttribute ()
268 XElement el = node as XElement;
269 if (el == null || !el.HasAttributes)
271 foreach (XAttribute a in el.Attributes ())
272 if (!a.IsNamespaceDeclaration) {
279 public override bool MoveToFirstChild ()
281 XContainer c = node as XContainer;
289 public override bool MoveToFirstNamespace (XPathNamespaceScope scope)
291 for (XElement el = node as XElement; el != null; el = el.Parent) {
292 foreach (XAttribute a in el.Attributes ())
293 if (a.IsNamespaceDeclaration) {
297 if (scope == XPathNamespaceScope.Local)
300 if (scope != XPathNamespaceScope.All)
307 public override bool MoveToId (string id)
312 public override bool MoveToNext ()
314 if (node.NextNode == null)
316 node = node.NextNode;
321 public override bool MoveToNextAttribute ()
325 if (attr.NextAttribute == null)
327 for (XAttribute a = attr.NextAttribute; a != null; a = a.NextAttribute)
328 if (!a.IsNamespaceDeclaration) {
335 public override bool MoveToNextNamespace (XPathNamespaceScope scope)
339 for (XAttribute a = attr.NextAttribute; a != null; a = a.NextAttribute)
340 if (a.IsNamespaceDeclaration) {
345 if (scope == XPathNamespaceScope.Local)
348 for (XElement el = ((XElement) attr.Parent).Parent; el != null; el = el.Parent) {
349 foreach (XAttribute a in el.Attributes ())
350 if (a.IsNamespaceDeclaration) {
355 if (scope != XPathNamespaceScope.All)
361 public override bool MoveToParent ()
367 if (node.Parent == null)
373 public override bool MoveToPrevious ()
375 if (node.PreviousNode == null)
377 node = node.PreviousNode;
382 public override void MoveToRoot ()