From fc8a05358a92cc3c77c5f1e30d536807ef0614fd Mon Sep 17 00:00:00 2001 From: Victoria Plitt Date: Mon, 8 Apr 2019 13:49:55 +0300 Subject: were added scripting projects --- .../Tango.Scripting.Editors/Xml/AXmlElement.cs | 226 +++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Xml/AXmlElement.cs (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Xml/AXmlElement.cs') diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Xml/AXmlElement.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Xml/AXmlElement.cs new file mode 100644 index 000000000..080d538e8 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Xml/AXmlElement.cs @@ -0,0 +1,226 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Globalization; +using System.Linq; + +using Tango.Scripting.Editors.Document; + +namespace Tango.Scripting.Editors.Xml +{ + /// + /// Logical grouping of other nodes together. + /// + public class AXmlElement: AXmlContainer + { + /// No tags are missing anywhere within this element (recursive) + public bool IsProperlyNested { get; set; } + /// True in wellformed XML + public bool HasStartOrEmptyTag { get; set; } + /// True in wellformed XML + public bool HasEndTag { get; set; } + + /// + internal override bool UpdateDataFrom(AXmlObject source) + { + if (!base.UpdateDataFrom(source)) return false; + AXmlElement src = (AXmlElement)source; + // Clear the cache for this - quite expensive + attributesAndElements = null; + if (this.IsProperlyNested != src.IsProperlyNested || + this.HasStartOrEmptyTag != src.HasStartOrEmptyTag || + this.HasEndTag != src.HasEndTag) + { + OnChanging(); + this.IsProperlyNested = src.IsProperlyNested; + this.HasStartOrEmptyTag = src.HasStartOrEmptyTag; + this.HasEndTag = src.HasEndTag; + OnChanged(); + return true; + } else { + return false; + } + } + + /// The start or empty-element tag if there is any + internal AXmlTag StartTag { + get { + Assert(HasStartOrEmptyTag, "Does not have a start tag"); + return (AXmlTag)this.Children[0]; + } + } + + /// The end tag if there is any + internal AXmlTag EndTag { + get { + Assert(HasEndTag, "Does not have an end tag"); + return (AXmlTag)this.Children[this.Children.Count - 1]; + } + } + + internal override void DebugCheckConsistency(bool checkParentPointers) + { + DebugAssert(Children.Count > 0, "No children"); + base.DebugCheckConsistency(checkParentPointers); + } + + #region Helpper methods + + /// Gets attributes of the element + /// + /// Warning: this is a cenvenience method to access the attributes of the start tag. + /// However, since the start tag might be moved/replaced, this property might return + /// different values over time. + /// + public AXmlAttributeCollection Attributes { + get { + if (this.HasStartOrEmptyTag) { + return this.StartTag.Attributes; + } else { + return AXmlAttributeCollection.Empty; + } + } + } + + ObservableCollection attributesAndElements; + + /// Gets both attributes and elements. Expensive, avoid use. + /// Warning: the collection will regenerate after each update + public ObservableCollection AttributesAndElements { + get { + if (attributesAndElements == null) { + if (this.HasStartOrEmptyTag) { + attributesAndElements = new MergedCollection> ( + // New wrapper with RawObject types + new FilteredCollection>(this.StartTag.Children, x => x is AXmlAttribute), + new FilteredCollection>(this.Children, x => x is AXmlElement) + ); + } else { + attributesAndElements = new FilteredCollection>(this.Children, x => x is AXmlElement); + } + } + return attributesAndElements; + } + } + + /// Name with namespace prefix - exactly as in source + public string Name { + get { + if (this.HasStartOrEmptyTag) { + return this.StartTag.Name; + } else { + return this.EndTag.Name; + } + } + } + + /// The part of name before ":" + /// Empty string if not found + public string Prefix { + get { + return GetNamespacePrefix(this.Name); + } + } + + /// The part of name after ":" + /// Empty string if not found + public string LocalName { + get { + return GetLocalName(this.Name); + } + } + + /// Resolved namespace of the name + /// Empty string if prefix is not found + public string Namespace { + get { + string prefix = this.Prefix; + if (string.IsNullOrEmpty(prefix)) { + return FindDefaultNamespace(); + } else { + return ResolvePrefix(prefix); + } + } + } + + /// Find the defualt namespace for this context + public string FindDefaultNamespace() + { + AXmlElement current = this; + while(current != null) { + string namesapce = current.GetAttributeValue(NoNamespace, "xmlns"); + if (namesapce != null) return namesapce; + current = current.Parent as AXmlElement; + } + return string.Empty; // No namesapce + } + + /// + /// Recursively resolve given prefix in this context. Prefix must have some value. + /// + /// Empty string if prefix is not found + public string ResolvePrefix(string prefix) + { + if (string.IsNullOrEmpty(prefix)) throw new ArgumentException("No prefix given", "prefix"); + + // Implicit namesapces + if (prefix == "xml") return XmlNamespace; + if (prefix == "xmlns") return XmlnsNamespace; + + AXmlElement current = this; + while(current != null) { + string namesapce = current.GetAttributeValue(XmlnsNamespace, prefix); + if (namesapce != null) return namesapce; + current = current.Parent as AXmlElement; + } + return NoNamespace; // Can not find prefix + } + + /// + /// Get unquoted value of attribute. + /// It looks in the no namespace (empty string). + /// + /// Null if not found + public string GetAttributeValue(string localName) + { + return GetAttributeValue(NoNamespace, localName); + } + + /// + /// Get unquoted value of attribute + /// + /// Namespace. Can be no namepace (empty string), which is the default for attributes. + /// Local name - text after ":" + /// Null if not found + public string GetAttributeValue(string @namespace, string localName) + { + @namespace = @namespace ?? string.Empty; + foreach(AXmlAttribute attr in this.Attributes.GetByLocalName(localName)) { + DebugAssert(attr.LocalName == localName, "Bad hashtable"); + if (attr.Namespace == @namespace) { + return attr.Value; + } + } + return null; + } + + #endregion + + /// + public override void AcceptVisitor(IAXmlVisitor visitor) + { + visitor.VisitElement(this); + } + + /// + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "[{0} '{1}' Attr:{2} Chld:{3} Nest:{4}]", base.ToString(), this.Name, this.HasStartOrEmptyTag ? this.StartTag.Children.Count : 0, this.Children.Count, this.IsProperlyNested ? "Ok" : "Bad"); + } + } +} -- cgit v1.3.1