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.
33 using System.Xml.Schema;
34 using System.Xml.XPath;
36 using XPI = System.Xml.Linq.XProcessingInstruction;
38 namespace System.Xml.Linq
40 internal class XNodeNavigator : XPathNavigator
42 static readonly XAttribute attr_ns_xml = new XAttribute (XNamespace.Xmlns.GetName ("xml"), XNamespace.Xml.NamespaceName);
46 XmlNameTable name_table;
48 public XNodeNavigator (XNode node, XmlNameTable nameTable)
51 this.name_table = nameTable;
54 public XNodeNavigator (XNodeNavigator other)
56 this.node = other.node;
57 this.attr = other.attr;
58 this.name_table = other.name_table;
61 public override string BaseURI {
62 get { return node.BaseUri ?? String.Empty; }
65 public override bool CanEdit {
69 public override bool HasAttributes {
71 XElement el = node as XElement;
72 return el != null && el.HasAttributes;
76 public override bool HasChildren {
78 XContainer c = node as XContainer;
79 return c != null && c.FirstNode != null;
83 public override bool IsEmptyElement {
85 XElement el = node as XElement;
86 return el != null && el.IsEmpty;
90 public override string LocalName {
93 case XPathNodeType.Namespace:
94 return attr.Name.Namespace == XNamespace.None ? String.Empty : attr.Name.LocalName;
95 case XPathNodeType.Attribute:
96 return attr.Name.LocalName;
97 case XPathNodeType.Element:
98 return ((XElement) node).Name.LocalName;
99 case XPathNodeType.ProcessingInstruction:
100 return ((XPI) node).Target;
107 public override string Name {
111 case XPathNodeType.Attribute:
114 case XPathNodeType.Element:
115 name = ((XElement) node).Name;
120 if (name.Namespace == XNamespace.None)
121 return name.LocalName;
122 XElement el = (node as XElement) ?? node.Parent;
124 return name.LocalName;
125 string prefix = el.GetPrefixOfNamespace (name.Namespace);
126 return prefix.Length > 0 ? String.Concat (prefix, ":", name.LocalName) : name.LocalName;
130 public override string NamespaceURI {
133 case XPathNodeType.Namespace:
135 case XPathNodeType.Attribute:
136 return attr.Name.NamespaceName;
137 case XPathNodeType.Element:
138 return ((XElement) node).Name.NamespaceName;
145 public override XmlNameTable NameTable {
146 get { return name_table; }
149 public override XPathNodeType NodeType {
152 return attr.IsNamespaceDeclaration ?
153 XPathNodeType.Namespace :
154 XPathNodeType.Attribute;
155 switch (node.NodeType) {
156 case XmlNodeType.Element:
157 return XPathNodeType.Element;
158 case XmlNodeType.Document:
159 return XPathNodeType.Root;
160 case XmlNodeType.Comment:
161 return XPathNodeType.Comment;
162 case XmlNodeType.ProcessingInstruction:
163 return XPathNodeType.ProcessingInstruction;
165 return XPathNodeType.Text;
170 public override string Prefix {
174 case XPathNodeType.Attribute:
177 case XPathNodeType.Element:
178 name = ((XElement) node).Name;
183 if (name.Namespace == XNamespace.None)
185 XElement el = (node as XElement) ?? node.Parent;
188 return el.GetPrefixOfNamespace (name.Namespace);
192 public override IXmlSchemaInfo SchemaInfo {
196 public override object UnderlyingObject {
197 get { return attr != null ? (object) attr : node; }
200 public override string Value {
206 case XPathNodeType.Comment:
207 return ((XComment) node).Value;
208 case XPathNodeType.ProcessingInstruction:
209 return ((XPI) node).Data;
210 case XPathNodeType.Text:
211 return ((XText) node).Value;
212 case XPathNodeType.Element:
213 case XPathNodeType.Root:
214 return GetInnerText ((XContainer) node);
220 string GetInnerText (XContainer node)
222 StringBuilder sb = null;
223 foreach (XNode n in node.Nodes ())
224 GetInnerText (n, ref sb);
225 return sb != null ? sb.ToString () : String.Empty;
228 void GetInnerText (XNode n, ref StringBuilder sb)
230 switch (n.NodeType) {
231 case XmlNodeType.Element:
232 foreach (XNode c in ((XElement) n).Nodes ())
233 GetInnerText (c, ref sb);
235 case XmlNodeType.Text:
236 case XmlNodeType.CDATA:
238 sb = new StringBuilder ();
239 sb.Append (((XText) n).Value);
244 public override XPathNavigator Clone ()
246 return new XNodeNavigator (this);
249 public override bool IsSamePosition (XPathNavigator other)
251 XNodeNavigator nav = other as XNodeNavigator;
252 if (nav == null || nav.node.Owner != node.Owner)
254 return node == nav.node && attr == nav.attr;
257 public override bool MoveTo (XPathNavigator other)
259 XNodeNavigator nav = other as XNodeNavigator;
260 if (nav == null || nav.node.Owner != node.Owner)
267 public override bool MoveToFirstAttribute ()
269 XElement el = node as XElement;
270 if (el == null || !el.HasAttributes)
272 foreach (XAttribute a in el.Attributes ())
273 if (!a.IsNamespaceDeclaration) {
280 public override bool MoveToFirstChild ()
282 XContainer c = node as XContainer;
283 if (c == null || c.FirstNode == null)
290 public override bool MoveToFirstNamespace (XPathNamespaceScope scope)
292 for (XElement el = node as XElement; el != null; el = el.Parent) {
293 foreach (XAttribute a in el.Attributes ())
294 if (a.IsNamespaceDeclaration) {
298 if (scope == XPathNamespaceScope.Local)
301 if (scope != XPathNamespaceScope.All)
307 public override bool MoveToId (string id)
309 throw new NotSupportedException ("This XPathNavigator does not support IDs");
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 ()