Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.11/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.Xml-5.5.0/AXmlReader.cs @ 15261

Last change on this file since 15261 was 11804, checked in by jkarder, 9 years ago

#2077:

  • added fancy xml documentation
  • fixed configurations and plattforms
File size: 12.8 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.Linq;
22using System.Text;
23using System.Xml;
24using ICSharpCode.NRefactory.Editor;
25
26namespace ICSharpCode.NRefactory.Xml
27{
28  /// <summary>
29  /// XmlReader implementation that reads from an <see cref="AXmlDocument"/>.
30  /// </summary>
31  sealed class AXmlReader : XmlReader, IXmlLineInfo
32  {
33    readonly ObjectIterator objectIterator;
34    readonly XmlReaderSettings settings;
35    Func<int, TextLocation> offsetToTextLocation;
36    readonly XmlNameTable nameTable;
37    readonly XmlNamespaceManager nsManager;
38    ReadState readState = ReadState.Initial;
39    XmlNodeType elementNodeType = XmlNodeType.None;
40    IList<InternalAttribute> attributes;
41    int attributeIndex = -1;
42    bool inAttributeValue;
43   
44    internal AXmlReader(ObjectIterator objectIterator, XmlReaderSettings settings = null, Func<int, TextLocation> offsetToTextLocation = null)
45    {
46      this.objectIterator = objectIterator;
47      this.settings = settings ?? new XmlReaderSettings();
48      this.offsetToTextLocation = offsetToTextLocation;
49      this.nameTable = this.settings.NameTable ?? new NameTable();
50      this.nsManager = new XmlNamespaceManager(this.nameTable);
51      objectIterator.StopAtElementEnd = true;
52    }
53   
54    public override void ResolveEntity()
55    {
56      throw new NotSupportedException();
57    }
58   
59    public override ReadState ReadState {
60      get { return readState; }
61    }
62   
63    public override XmlReaderSettings Settings {
64      get { return settings; }
65    }
66   
67    public override bool ReadAttributeValue()
68    {
69      if (attributeIndex >= 0 && !inAttributeValue) {
70        inAttributeValue = true;
71        return true;
72      }
73      return false;
74    }
75   
76    public override bool Read()
77    {
78      switch (readState) {
79        case ReadState.Initial:
80          readState = ReadState.Interactive;
81          return ReadCurrentPosition();
82        case ReadState.Interactive:
83          LeaveNode();
84          objectIterator.MoveInto();
85          return ReadCurrentPosition();
86        default:
87          return false;
88      }
89    }
90   
91    bool ReadCurrentPosition()
92    {
93      attributes = null;
94      attributeIndex = -1;
95      inAttributeValue = false;
96      while (true) {
97        var obj = objectIterator.CurrentObject;
98        if (obj == null) {
99          readState = ReadState.EndOfFile;
100          elementNodeType = XmlNodeType.None;
101          return false;
102        } else if (objectIterator.IsAtElementEnd) {
103          if (IsEmptyElement) {
104            // Don't report EndElement for empty elements
105            nsManager.PopScope();
106          } else {
107            elementNodeType = XmlNodeType.EndElement;
108            return true;
109          }
110        } else if (obj is InternalElement) {
111          // element start
112          elementNodeType = XmlNodeType.Element;
113          InternalTag startTag = ((InternalTag)obj.NestedObjects[0]);
114          nsManager.PushScope();
115          if (startTag.NestedObjects != null) {
116            attributes = startTag.NestedObjects.OfType<InternalAttribute>().ToList();
117            for (int i = 0; i < attributes.Count; i++) {
118              var attr = attributes[i];
119              if (attr.Name.StartsWith("xmlns:", StringComparison.Ordinal))
120                nsManager.AddNamespace(AXmlObject.GetLocalName(attr.Name), attr.Value);
121              else if (attr.Name == "xmlns")
122                nsManager.AddNamespace(string.Empty, attr.Value);
123            }
124          }
125          return true;
126        } else if (obj is InternalText) {
127          InternalText text = (InternalText)obj;
128          if (text.ContainsOnlyWhitespace) {
129            elementNodeType = XmlNodeType.Whitespace;
130          } else {
131            elementNodeType = XmlNodeType.Text;
132          }
133          return true;
134        } else if (obj is InternalTag) {
135          InternalTag tag = (InternalTag)obj;
136          if (tag.IsStartOrEmptyTag || tag.IsEndTag) {
137            // start/end tags can be skipped as the parent InternalElement already handles them
138          } else if (tag.IsComment && !settings.IgnoreComments) {
139            elementNodeType = XmlNodeType.Comment;
140            return true;
141          } else if (tag.IsProcessingInstruction && !settings.IgnoreProcessingInstructions) {
142            if (tag.Name == "xml") {
143              elementNodeType = XmlNodeType.XmlDeclaration;
144              attributes = tag.NestedObjects.OfType<InternalAttribute>().ToList();
145            } else {
146              elementNodeType = XmlNodeType.ProcessingInstruction;
147            }
148            return true;
149          } else if (tag.IsCData) {
150            elementNodeType = XmlNodeType.CDATA;
151            return true;
152          } else {
153            // TODO all other tags
154          }
155        } else {
156          throw new NotSupportedException();
157        }
158        objectIterator.MoveInto();
159      }
160    }
161   
162    void LeaveNode()
163    {
164      if (elementNodeType == XmlNodeType.EndElement) {
165        nsManager.PopScope();
166      }
167    }
168   
169    public override void Skip()
170    {
171      if (readState == ReadState.Interactive) {
172        MoveToElement();
173        LeaveNode();
174        objectIterator.MoveNext();
175        ReadCurrentPosition();
176      }
177    }
178   
179    public override string Prefix {
180      get {
181        if (readState != ReadState.Interactive)
182          return string.Empty;
183        if (attributeIndex >= 0) {
184          if (inAttributeValue)
185            return string.Empty;
186          return nameTable.Add(AXmlObject.GetNamespacePrefix(attributes[attributeIndex].Name));
187        }
188        InternalElement element = objectIterator.CurrentObject as InternalElement;
189        return element != null ? nameTable.Add(element.Prefix) : string.Empty;
190      }
191    }
192   
193    public override string NamespaceURI {
194      get {
195        if (readState != ReadState.Interactive)
196          return string.Empty;
197        if (attributeIndex >= 0 && !inAttributeValue && attributes[attributeIndex].Name == "xmlns")
198          return AXmlObject.XmlnsNamespace;
199        return LookupNamespace(this.Prefix) ?? string.Empty;
200      }
201    }
202   
203    public override string LocalName {
204      get {
205        if (readState != ReadState.Interactive)
206          return string.Empty;
207        if (attributeIndex >= 0) {
208          if (inAttributeValue)
209            return string.Empty;
210          return nameTable.Add(AXmlObject.GetLocalName(attributes[attributeIndex].Name));
211        }
212        string result;
213        switch (elementNodeType) {
214          case XmlNodeType.Element:
215          case XmlNodeType.EndElement:
216            result = ((InternalElement)objectIterator.CurrentObject).LocalName;
217            break;
218          case XmlNodeType.XmlDeclaration:
219            result = "xml";
220            break;
221          default:
222            return string.Empty;
223        }
224        return nameTable.Add(result);
225      }
226    }
227   
228    public override string Name {
229      get {
230        if (readState != ReadState.Interactive)
231          return string.Empty;
232        if (attributeIndex >= 0) {
233          if (inAttributeValue)
234            return string.Empty;
235          return nameTable.Add(attributes[attributeIndex].Name);
236        }
237        string result;
238        switch (elementNodeType) {
239          case XmlNodeType.Element:
240          case XmlNodeType.EndElement:
241            result = ((InternalElement)objectIterator.CurrentObject).Name;
242            break;
243          case XmlNodeType.XmlDeclaration:
244            result = "xml";
245            break;
246          default:
247            return string.Empty;
248        }
249        return nameTable.Add(result);
250      }
251    }
252   
253    public override bool IsEmptyElement {
254      get {
255        if (readState != ReadState.Interactive || attributeIndex >= 0)
256          return false;
257        InternalElement element = objectIterator.CurrentObject as InternalElement;
258        return element != null && element.NestedObjects.Length == 1;
259      }
260    }
261   
262    public override string Value {
263      get {
264        if (readState != ReadState.Interactive)
265          return string.Empty;
266        if (attributeIndex >= 0)
267          return attributes[attributeIndex].Value;
268        switch (elementNodeType) {
269          case XmlNodeType.Text:
270          case XmlNodeType.Whitespace:
271            return ((InternalText)objectIterator.CurrentObject).Value;
272          case XmlNodeType.Comment:
273          case XmlNodeType.CDATA:
274            var nestedObjects = objectIterator.CurrentObject.NestedObjects;
275            if (nestedObjects.Length == 1)
276              return ((InternalText)nestedObjects[0]).Value;
277            else
278              return string.Empty;
279          case XmlNodeType.XmlDeclaration:
280            StringBuilder b = new StringBuilder();
281            foreach (var attr in objectIterator.CurrentObject.NestedObjects.OfType<InternalAttribute>()) {
282              if (b.Length > 0)
283                b.Append(' ');
284              b.Append(attr.Name);
285              b.Append('=');
286              b.Append('"');
287              b.Append(attr.Value);
288              b.Append('"');
289            }
290            return b.ToString();
291          default:
292            return string.Empty;
293        }
294      }
295    }
296   
297    public override bool HasValue {
298      get {
299        if (readState != ReadState.Interactive)
300          return false;
301        if (attributeIndex >= 0)
302          return true;
303        switch (elementNodeType) {
304          case XmlNodeType.Text:
305          case XmlNodeType.Whitespace:
306          case XmlNodeType.Comment:
307          case XmlNodeType.XmlDeclaration:
308          case XmlNodeType.CDATA:
309            return true;
310          default:
311            return false;
312        }
313      }
314    }
315   
316    public override XmlNodeType NodeType {
317      get {
318        if (attributeIndex >= 0)
319          return inAttributeValue ? XmlNodeType.Text : XmlNodeType.Attribute;
320        else
321          return elementNodeType;
322      }
323    }
324   
325    public override XmlNameTable NameTable {
326      get { return nameTable; }
327    }
328   
329    public override bool MoveToFirstAttribute()
330    {
331      return DoMoveToAttribute(0);
332    }
333   
334    public override bool MoveToNextAttribute()
335    {
336      return DoMoveToAttribute(attributeIndex + 1);
337    }
338   
339    public override void MoveToAttribute(int i)
340    {
341      if (!DoMoveToAttribute(i))
342        throw new ArgumentOutOfRangeException("i");
343    }
344   
345    bool DoMoveToAttribute(int i)
346    {
347      if (i >= 0 && i < this.AttributeCount) {
348        attributeIndex = i;
349        inAttributeValue = false;
350        return true;
351      }
352      return false;
353    }
354   
355    public override bool MoveToElement()
356    {
357      if (attributeIndex >= 0) {
358        attributeIndex = -1;
359        inAttributeValue = false;
360        return true;
361      }
362      return false;
363    }
364   
365    int GetAttributeIndex(string name)
366    {
367      if (attributes == null)
368        return -1;
369      for (int i = 0; i < attributes.Count; i++) {
370        if (attributes[i].Name == name)
371          return i;
372      }
373      return -1;
374    }
375   
376    int GetAttributeIndex(string name, string ns)
377    {
378      if (attributes == null)
379        return -1;
380      for (int i = 0; i < attributes.Count; i++) {
381        if (AXmlObject.GetLocalName(attributes[i].Name) == name && (LookupNamespace(AXmlObject.GetNamespacePrefix(attributes[i].Name)) ?? string.Empty) == ns)
382          return i;
383      }
384      return -1;
385    }
386   
387    public override bool MoveToAttribute(string name, string ns)
388    {
389      return DoMoveToAttribute(GetAttributeIndex(name, ns));
390    }
391   
392    public override bool MoveToAttribute(string name)
393    {
394      return DoMoveToAttribute(GetAttributeIndex(name));
395    }
396   
397    public override string LookupNamespace(string prefix)
398    {
399      return nsManager.LookupNamespace(prefix);
400    }
401   
402    public override string GetAttribute(int i)
403    {
404      if (attributes == null || i < 0 || i >= attributes.Count)
405        return null;
406      return attributes[i].Value;
407    }
408   
409    public override string GetAttribute(string name, string namespaceURI)
410    {
411      return GetAttribute(GetAttributeIndex(name, namespaceURI));
412    }
413   
414    public override string GetAttribute(string name)
415    {
416      return GetAttribute(GetAttributeIndex(name));
417    }
418   
419    public override bool EOF {
420      get { return readState == ReadState.EndOfFile; }
421    }
422   
423    public override int Depth {
424      get {
425        if (attributeIndex < 0)
426          return objectIterator.Depth;
427        else
428          return objectIterator.Depth + (inAttributeValue ? 2 : 1);
429      }
430    }
431   
432    public override void Close()
433    {
434      readState = ReadState.Closed;
435      offsetToTextLocation = null;
436    }
437   
438    public override string BaseURI {
439      get { return string.Empty; }
440    }
441   
442    public override int AttributeCount {
443      get { return attributes != null ? attributes.Count : 0; }
444    }
445   
446    int CurrentPosition {
447      get {
448        if (attributeIndex < 0)
449          return objectIterator.CurrentPosition;
450        else
451          return objectIterator.CurrentPosition + attributes[attributeIndex].StartRelativeToParent;
452      }
453    }
454   
455    public int LineNumber {
456      get {
457        if (offsetToTextLocation != null)
458          return offsetToTextLocation(CurrentPosition).Line;
459        else
460          return 0;
461      }
462    }
463   
464    public int LinePosition {
465      get {
466        if (offsetToTextLocation != null)
467          return offsetToTextLocation(CurrentPosition).Column - 1;
468        else
469          return 0;
470      }
471    }
472   
473    bool IXmlLineInfo.HasLineInfo()
474    {
475      return offsetToTextLocation != null;
476    }
477  }
478}
Note: See TracBrowser for help on using the repository browser.