/** * @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); }
private object ParseAttributeMarkup (XamlObjectElement element, XamlPropertySetter property, XamlAttribute ai) { MarkupExpressionParser parser = new SL4MarkupExpressionParser (element.Object, property.Name, this, element); string expression = ai.Value; object o = null; try { o = parser.ParseExpression (ref expression); } catch (Exception e) { throw ParseException ("Could not convert attribute value '{0}' on element {1} for property {2}.", ai.Value, element.Name, property.Name); } if (o == null && !MarkupExpressionParser.IsExplicitNull (expression)) throw ParseException ("Unable to convert attribute value: '{0}'.", ai.Value); return property.ConvertValue (property.Type, o); }
/** @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; }
private object ParseAttributeValue (XamlObjectElement element, XamlPropertySetter property, XamlAttribute ai) { object value = null; if (IsMarkupExpression (ai.Value)) value = ParseAttributeMarkup (element, property, ai); else { try { value = property.ConvertTextValue (ai.Value); } catch (Exception ex) { throw ParseException ("Could not convert attribute value '{0}' on element {1} for property {2}.", ai.Value, element.Name, property.Name); } } return value; }
private void ParseXmlDirective (XamlElement element, XamlAttribute ai) { if (ai.LocalName == "space") { // Do nothing XmlReader covers this for us } }
private void ParseXAttribute (XamlObjectElement element, XamlAttribute ai) { switch (ai.LocalName) { case "Key": RegisterKeyItem (element, element.Parent, ai.Value); return; case "Name": RegisterNamedItem (element, ai.Value); return; case "Class": // The class attribute is handled when we initialize the element return; case "ClassModifier": case "FieldModifier": // There are no docs on whether these change anything // internally on silverlight. // But I think they are only a tooling issue. return; case "Uid": // This attribute is just ignored, but allowed. return; default: throw ParseException ("Unknown x: attribute ({0}).", ai.LocalName); } }
private void ParseAttribute (XamlObjectElement element, XamlAttribute ai) { Log ("\t\t\tParseAttribute {0}", ai.Name); if (ai.IsNsXaml) { ParseXAttribute (element, ai); return; } if (ai.IsXmlDirective) { ParseXmlDirective (element, ai); return; } XamlPropertySetter prop = element.LookupProperty (ai); if (prop == null) throw ParseException ("The property {0} was not found on element {1}.", ai.LocalName, element.Name); object value = ParseAttributeValue (element, prop, ai); Log ("\t\t\t\tSetting Property {0} {1} {2} {3}", prop, element.Object, ai, value); prop.SetValue (element, value); }
void XamlNode_OnAttribute (XamlNode node, XamlAttribute ai) { if (!(CurrentElement is XamlObjectElement)) return; if (IsStaticResourceElement ()) return; currentNode = ai; ParseAttribute (CurrentElement as XamlObjectElement, ai); currentNode = node; }