Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.Xml-5.5.0/AXmlElement.cs @ 16723

Last change on this file since 16723 was 11804, checked in by jkarder, 10 years ago

#2077:

  • added fancy xml documentation
  • fixed configurations and plattforms
File size: 8.1 KB
Line 
1// Copyright (c) 2009-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Collections.Generic;
21using System.Globalization;
22using System.Linq;
23using System.Xml;
24
25namespace ICSharpCode.NRefactory.Xml
26{
27  /// <summary>
28  /// XML element.
29  /// </summary>
30  public class AXmlElement : AXmlObject, IXmlNamespaceResolver
31  {
32    internal AXmlElement(AXmlObject parent, int startOffset, InternalElement internalObject)
33      : base(parent, startOffset, internalObject)
34    {
35      Log.Assert(internalObject.NestedObjects[0] is InternalTag, "First child of element must be start tag");
36    }
37   
38    /// <summary> No tags are missing anywhere within this element (recursive) </summary>
39    public bool IsProperlyNested {
40      get { return ((InternalElement)internalObject).IsPropertyNested; }
41    }
42   
43    /// <summary>The start or empty-element tag for this element.</summary>
44    public AXmlTag StartTag {
45      get { return (AXmlTag)this.Children[0]; }
46    }
47   
48    /// <summary>Name with namespace prefix - exactly as in source</summary>
49    public string Name {
50      get { return ((InternalTag)internalObject.NestedObjects[0]).Name; }
51    }
52   
53    /// <summary>Gets whether an end tag exists for this node.</summary>
54    public bool HasEndTag {
55      get { return ((InternalElement)internalObject).HasEndTag; }
56    }
57   
58    /// <summary> The end tag, if there is any. Returns null for empty elements "&lt;Element/>" and missing end tags in malformed XML.</summary>
59    public AXmlTag EndTag {
60      get {
61        if (HasEndTag)
62          return (AXmlTag)this.Children[this.Children.Count - 1];
63        else
64          return null;
65      }
66    }
67   
68    /// <summary>
69    /// Gets the attributes.
70    /// </summary>
71    public IEnumerable<AXmlAttribute> Attributes {
72      get {
73        return ((AXmlTag)this.Children[0]).Children.OfType<AXmlAttribute>();
74      }
75    }
76   
77    /// <summary>
78    /// Gets the content (all children except for the start and end tags)
79    /// </summary>
80    public IEnumerable<AXmlObject> Content {
81      get {
82        int end = this.Children.Count;
83        if (HasEndTag)
84          end--;
85        for (int i = 1; i < end; i++) {
86          yield return this.Children[i];
87        }
88      }
89    }
90   
91    /// <summary> The part of name before ":" </summary>
92    /// <returns> Empty string if not found </returns>
93    public string Prefix {
94      get { return ((InternalElement)internalObject).Prefix; }
95    }
96   
97    /// <summary> The part of name after ":" </summary>
98    /// <returns> Empty string if not found </returns>
99    public string LocalName {
100      get { return ((InternalElement)internalObject).LocalName; }
101    }
102   
103    /// <summary> Resolved namespace of the name </summary>
104    /// <returns> Empty string if prefix is not found </returns>
105    public string Namespace {
106      get {
107        string prefix = this.Prefix;
108        return LookupNamespace(prefix);
109      }
110    }
111   
112    /// <summary> Find the default namespace for this context </summary>
113    [Obsolete("Use LookupNamespace(string.Empty) instead")]
114    public string FindDefaultNamespace()
115    {
116      return LookupNamespace(string.Empty) ?? NoNamespace;
117    }
118   
119    /// <summary>
120    /// Recursively resolve given prefix in this context.  Prefix must have some value.
121    /// </summary>
122    /// <returns> Empty string if prefix is not found </returns>
123    [Obsolete("Use LookupNamespace() instead")]
124    public string ResolvePrefix(string prefix)
125    {
126      return LookupNamespace(prefix) ?? NoNamespace;
127    }
128   
129    /// <summary>
130    /// Recursively resolve given prefix in this context.
131    /// </summary>
132    /// <returns><c>null</c> if prefix is not found</returns>
133    public string LookupNamespace(string prefix)
134    {
135      if (prefix == null)
136        throw new ArgumentNullException("prefix");
137     
138      // Implicit namespaces
139      if (prefix == "xml") return XmlNamespace;
140      if (prefix == "xmlns") return XmlnsNamespace;
141     
142      string lookFor = (prefix.Length > 0 ? "xmlns:" + prefix : "xmlns");
143      for (AXmlElement current = this; current != null; current = current.Parent as AXmlElement) {
144        foreach (var attr in current.Attributes) {
145          if (attr.Name == lookFor)
146            return attr.Value;
147        }
148      }
149      return null; // Can not find prefix
150    }
151   
152    /// <summary>
153    /// Gets the prefix that is mapped to the specified namespace URI.
154    /// </summary>
155    /// <returns>The prefix that is mapped to the namespace URI; null if the namespace URI is not mapped to a prefix.</returns>
156    public string LookupPrefix(string namespaceName)
157    {
158      if (namespaceName == null)
159        throw new ArgumentNullException("namespaceName");
160     
161      if (namespaceName == XmlNamespace)
162        return "xml";
163      if (namespaceName == XmlnsNamespace)
164        return "xmlns";
165      for (AXmlElement current = this; current != null; current = current.Parent as AXmlElement) {
166        foreach (var attr in current.Attributes) {
167          if (attr.Value == namespaceName) {
168            if (attr.Name.StartsWith("xmlns:", StringComparison.Ordinal))
169              return attr.LocalName;
170            else if (attr.Name == "xmlns")
171              return string.Empty;
172          }
173        }
174      }
175      return null; // Can not find prefix
176    }
177   
178    /// <summary>
179    /// Gets a collection of defined prefix-namespace mappings that are currently in scope.
180    /// </summary>
181    public IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
182    {
183      var result = new Dictionary<string, string>();
184      if (scope == XmlNamespaceScope.All) {
185        result["xml"] = XmlNamespace;
186        //result["xmlns"] = XmlnsNamespace; xmlns should not be included in GetNamespacesInScope() results
187      }
188      for (AXmlElement current = this; current != null; current = current.Parent as AXmlElement) {
189        foreach (var attr in current.Attributes) {
190          if (attr.Name.StartsWith("xmlns:", StringComparison.Ordinal)) {
191            string prefix = attr.LocalName;
192            if (!result.ContainsKey(prefix)) {
193              result.Add(prefix, attr.Value);
194            }
195          } else if (attr.Name == "xmlns" && !result.ContainsKey(string.Empty)) {
196            result.Add(string.Empty, attr.Value);
197          }
198        }
199        if (scope == XmlNamespaceScope.Local)
200          break;
201      }
202      return result;
203    }
204   
205    /// <summary>
206    /// Get unquoted value of attribute.
207    /// It looks in the no namespace (empty string).
208    /// </summary>
209    /// <returns>Null if not found</returns>
210    public string GetAttributeValue(string localName)
211    {
212      return GetAttributeValue(string.Empty, localName);
213    }
214   
215    /// <summary>
216    /// Get unquoted value of attribute
217    /// </summary>
218    /// <param name="namespace">Namespace.  Can be no namepace (empty string), which is the default for attributes.</param>
219    /// <param name="localName">Local name - text after ":"</param>
220    /// <returns>Null if not found</returns>
221    public string GetAttributeValue(string @namespace, string localName)
222    {
223      @namespace = @namespace ?? string.Empty;
224      foreach (AXmlAttribute attr in this.Attributes) {
225        if (attr.LocalName == localName && attr.Namespace == @namespace)
226          return attr.Value;
227      }
228      return null;
229    }
230   
231    /// <inheritdoc/>
232    public override void AcceptVisitor(AXmlVisitor visitor)
233    {
234      visitor.VisitElement(this);
235    }
236   
237    /// <inheritdoc/>
238    public override string ToString()
239    {
240      return string.Format(CultureInfo.InvariantCulture, "[{0} '{1}' Attr:{2} Chld:{3} Nest:{4}]", base.ToString(), this.Name, this.StartTag.Children.Count, this.Children.Count, this.IsProperlyNested ? "Ok" : "Bad");
241    }
242  }
243}
Note: See TracBrowser for help on using the repository browser.