public static XamlNode Parse (string xml, NodeEvent evstart, NodeEvent evend, AttributeEvent evattr) { XamlNode root; bool exists = cache.TryGetValue (xml, out root); if (!exists) root = new XamlNode () { outerXml = xml }; root.Parse (evstart, evend, evattr); if (!exists) cache[xml] = root; return root; }
/** @node If it's not null, it probably means we're on the top node and just got called from public Parse method @parent If it's null, it means we're on the top node @skip don't do a read, we're already on the next node and ready to process it If this method returns null, it means it has reached the end of the current xml subtree (the end element of the parent node) **/ static XamlNode Parse (XmlReader reader, XamlNode parent, XamlNode node, NodeEvent evstart, NodeEvent evend, AttributeEvent evattr, bool skip = false) { if (!skip) reader.Read (); if (parent == null) { while (reader.NodeType != XmlNodeType.Element) if (!reader.Read ()) return null; } else { do { while (reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Text) { if (!reader.Read ()) return null; } if (reader.NodeType == XmlNodeType.Element && parent.top.IgnorablePrefixes.Contains (reader.Prefix)) reader.Skip (); else break; } while (true); } if (reader.NodeType == XmlNodeType.EndElement) return null; if (node == null) node = new XamlNode (); node.Parsed = false; node.Ignore = false; if (!node.Initialized) { node.parent = parent; if (parent != null) node.top = parent.top; else { node.ignorablePrefixes = new List<string> (); node.top = node; } node.type = reader.NodeType; node.namespaceURI = reader.NamespaceURI; node.prefix = reader.Prefix; node.name = reader.Name; node.localName = reader.LocalName; node.IsEmptyElement = reader.IsEmptyElement; node.HasValue = reader.HasValue; node.XmlSpace = reader.XmlSpace; node.LineNumber = -1; node.LinePosition = -1; node.IsNsXaml = node.NamespaceURI == XamlUri; node.IsNsClr = node.NamespaceURI.StartsWith ("clr-namespace"); if (parent == null) node.DefaultXmlns = reader.GetAttribute ("xmlns"); if (node.IsNsClr) { int end = node.NamespaceURI.IndexOf (';'); if (end == -1) end = node.NamespaceURI.Length; node.ClrNamespace = node.NamespaceURI.Substring (14, end - 14); } if (node.IsNsClr && node.NamespaceURI.IndexOf (";assembly=") + 10 < node.NamespaceURI.Length) node.Assembly = node.NamespaceURI.Substring (node.NamespaceURI.IndexOf (";assembly=") + 10); if (node.HasValue) node.val = reader.Value; IXmlLineInfo linfo = reader as IXmlLineInfo; if (linfo != null) { node.LineNumber = linfo.LineNumber; node.LinePosition = linfo.LinePosition; } if (reader.HasAttributes) { string ig = reader.GetAttribute ("Ignorable", IgnorableUri); if (ig != null) { foreach (string s in ig.Split (' ')) node.IgnorablePrefixes.Add (s); } reader.MoveToFirstAttribute (); int count = 0; do { // this filters out ignorable attributes if (node.IgnorablePrefixes.Contains (reader.Prefix)) continue; XamlAttribute ai = new XamlAttribute (reader) { Index = count++, }; // an x: or equivalent attribute ai.IsNsXaml = !ai.IsMapping && ai.NamespaceURI == XamlUri; // an mc: or equivalent attribute (this attribute defines the list of ignorable prefixes) ai.IsNsIgnorable = !ai.IsMapping && (ai.NamespaceURI == IgnorableUri || ai.Prefix == "mc"); // an xmlns:my='clr-namespace...' attribute ai.IsNsClr = !ai.IsMapping && ai.NamespaceURI.StartsWith ("clr-namespace"); if (ai.IsNsXaml && ai.LocalName == "Class") node.Class = ai.Value; if (ai.IsMapping) { if (node.top != node) ai.Index = node.top.Attributes.Count; node.top.Attributes [reader.Name] = ai; } else { if (ai.IsNsXaml) { if (ai.LocalName == "Key") node.X_Key = ai.Value; else if (ai.LocalName == "Name") node.X_Name = ai.Value; } node.Attributes [reader.Name] = ai; } } while (reader.MoveToNextAttribute ()); reader.MoveToElement (); } node.Initialized = true; } if (evstart != null && (node.NodeType == XmlNodeType.Element || node.NodeType == XmlNodeType.Text)) evstart (node); if (evattr != null) { foreach (XamlAttribute ai in node.Attributes.Values.Where (x => !x.IsNsIgnorable && !x.IsMapping)) evattr (node, ai); } if (node.Ignore) { node.outerXml = reader.ReadOuterXml (); cache [node.outerXml] = node; if (evend != null && node.NodeType == XmlNodeType.Element) evend (node); return node; } if (node.NodeType == XmlNodeType.Element && !node.IsEmptyElement) { XamlNode child = null; do { child = Parse (reader, node, null, evstart, evend, evattr, child != null ? child.Ignore : false); if (child != null) { child.Parsed = !child.Ignore; node.Children.Add (child); } } while (child != null); } if (evend != null && node.NodeType == XmlNodeType.Element) evend (node); return node; }
internal XamlContext (XamlContext parent, object top_element, List<DependencyObject> resources, FrameworkTemplate template, XamlNode node) { Parent = parent; TopElement = top_element; Resources = resources; Template = template; Node = node; // // Its just not worth the lookup time to try accessing these on the parents, so copy them over. // XmlnsCachedTypes = new Dictionary<XmlNsKey, Type>(); }