public static XmlParseInfo Read(string text) { var nodes = new List <CompletionPathNode>(); var info = new XmlParseInfo { Nodes = nodes, Mode = CompletionMode.Class }; // complete the last node and/or attribute so the reader can find it. string supplement = null; bool hadLetter = false; char last = char.MinValue; for (int i = text.Length - 1; i >= 0; i--) { var ch = text[i]; if (ch == '<') { if (i == text.Length - 1) { break; } if (last == '/') // we're in an ending tag { info.Mode = CompletionMode.None; } if (supplement != null) { text += supplement; } text += ">"; break; } if (ch == '>') { info.Mode = CompletionMode.Class; break; } if (info.Mode == CompletionMode.Class) { if (ch == '=') { info.Mode = CompletionMode.Value; text = text.Substring(0, i + 1); supplement = "''"; } if (ch == '.') { info.Mode = CompletionMode.Property; } if (ch == ' ') { info.Mode = CompletionMode.Property; if (hadLetter) { supplement = "=''"; } } if (char.IsLetterOrDigit(ch)) { hadLetter = true; } } last = ch; } CompletionPathNode current = null; CompletionPathNode attribute = null; try { using (var stream = GetStream(text)) using (var reader = XmlReader.Create(stream)) { while (reader.Read()) { attribute = null; switch (reader.NodeType) { case XmlNodeType.Element: if (reader.IsEmptyElement) { continue; } nodes.Add(current = new CompletionPathNode(reader.Prefix, reader.LocalName, CompletionMode.Class)); if (reader.HasAttributes && reader.MoveToFirstAttribute()) { do { if (reader.Name == "xmlns" || reader.Prefix == "xmlns") { // record namespaces if (current.Namespaces == null) { current.Namespaces = new List <CompletionNamespace>(); } var prefix = reader.Prefix == "xmlns" ? reader.LocalName : string.Empty; current.Namespaces.Add(new CompletionNamespace { Prefix = prefix, Namespace = reader.Value }); } else { current.Attributes.Add(reader.Name); attribute = new CompletionPathNode(reader.Prefix, reader.LocalName, CompletionMode.Property); } } while (reader.MoveToNextAttribute()); } break; case XmlNodeType.EndElement: if (nodes.Count > 0) { nodes.RemoveAt(nodes.Count - 1); } current = nodes.Count > 0 ? nodes[nodes.Count - 1] : null; break; default: break; } } } } catch (XmlException) { // ignore errors, since xml will usually be incomplete } if (info.Mode == CompletionMode.Value && attribute != null) { nodes.Add(attribute); } return(info); }
public static XmlParseInfo Read(string text) { var nodes = new List <CompletionPathNode>(); var info = new XmlParseInfo { Nodes = nodes, Mode = CompletionMode.None }; // check the last part of the xml to see what type of completion we are in // and complete it so we can parse the property or class name. Match m; if ((m = valueReg.Match(text)).Success) { info.Mode = CompletionMode.Value; // without an actual value, xmlns doesn't parse, so put a dummy value here text = text.Substring(0, m.Index) + "'value'>"; } else if (classReg.Match(text).Success) { info.Mode = CompletionMode.Class; text += ">"; } else if (propertyReg.Match(text).Success) { int i = text.Length - 1; while (i > 0 && !char.IsWhiteSpace(text[i]) && text[i] != '<') { i--; } if (i < text.Length - 1) { text = text.Substring(0, i + 1); } info.Mode = CompletionMode.Property; text += ">"; } else if (classPropertyReg.Match(text).Success) { info.Mode = CompletionMode.Property; info.IsChildProperty = true; text += ">"; } CompletionPathNode current = null; CompletionPathNode attribute = null; try { using (var reader = XmlReader.Create(new StringReader(text))) { while (reader.Read()) { attribute = null; switch (reader.NodeType) { case XmlNodeType.Element: if (reader.IsEmptyElement) { continue; } nodes.Add(current = new CompletionPathNode(reader.Prefix, reader.LocalName, CompletionMode.Class)); if (reader.HasAttributes && reader.MoveToFirstAttribute()) { do { if (reader.Name == "xmlns" || reader.Prefix == "xmlns") { // record namespaces if (current.Namespaces == null) { current.Namespaces = new List <CompletionNamespace>(); } var prefix = reader.Prefix == "xmlns" ? reader.LocalName : string.Empty; current.Namespaces.Add(new CompletionNamespace { Prefix = prefix, Namespace = reader.Value }); var name = reader.LocalName; if (!string.IsNullOrEmpty(reader.Prefix)) { name = reader.Prefix + ":" + name; } attribute = new CompletionPathNode(string.Empty, name, CompletionMode.Property); } else { current.Attributes.Add(reader.Name); attribute = new CompletionPathNode(reader.Prefix, reader.LocalName, CompletionMode.Property); } } while (reader.MoveToNextAttribute()); } break; case XmlNodeType.EndElement: if (nodes.Count > 0) { nodes.RemoveAt(nodes.Count - 1); } current = nodes.Count > 0 ? nodes[nodes.Count - 1] : null; break; default: break; } } } } catch (XmlException) { // ignore errors, since xml will usually be incomplete } if (current?.LocalName.Contains(".") == true && info.Mode == CompletionMode.None && current.Mode == CompletionMode.Class) { current.LocalName = current.LocalName.Substring(current.LocalName.IndexOf('.') + 1); current.Mode = CompletionMode.Property; info.Mode = CompletionMode.Value; } if (info.Mode == CompletionMode.Value && attribute != null) { nodes.Add(attribute); } return(info); }
public static XmlParseInfo Read(string text) { var nodes = new List <CompletionPathNode>(); var info = new XmlParseInfo { Nodes = nodes, Mode = CompletionMode.None }; // check the last part of the xml to see what type of completion we are in // and complete it so we can parse the property or class name. var m = valueReg.Match(text); if (m.Success) { info.Mode = CompletionMode.Value; text = text.Substring(0, m.Index) + "''>"; } else { m = classReg.Match(text); if (m.Success) { info.Mode = CompletionMode.Class; } else { m = propertyReg.Match(text); if (m.Success) { info.Mode = CompletionMode.Property; } } text += ">"; } CompletionPathNode current = null; CompletionPathNode attribute = null; try { using (var stream = GetStream(text)) using (var reader = XmlReader.Create(stream)) { while (reader.Read()) { attribute = null; switch (reader.NodeType) { case XmlNodeType.Element: if (reader.IsEmptyElement) { continue; } nodes.Add(current = new CompletionPathNode(reader.Prefix, reader.LocalName, CompletionMode.Class)); if (reader.HasAttributes && reader.MoveToFirstAttribute()) { do { if (reader.Name == "xmlns" || reader.Prefix == "xmlns") { // record namespaces if (current.Namespaces == null) { current.Namespaces = new List <CompletionNamespace>(); } var prefix = reader.Prefix == "xmlns" ? reader.LocalName : string.Empty; current.Namespaces.Add(new CompletionNamespace { Prefix = prefix, Namespace = reader.Value }); } else { current.Attributes.Add(reader.Name); attribute = new CompletionPathNode(reader.Prefix, reader.LocalName, CompletionMode.Property); } } while (reader.MoveToNextAttribute()); } break; case XmlNodeType.EndElement: if (nodes.Count > 0) { nodes.RemoveAt(nodes.Count - 1); } current = nodes.Count > 0 ? nodes[nodes.Count - 1] : null; break; default: break; } } } } catch (XmlException) { // ignore errors, since xml will usually be incomplete } if (info.Mode == CompletionMode.Value && attribute != null) { nodes.Add(attribute); } return(info); }