public Element Parse()
        { // seperate because there are only a handful of valid top-level elements that should be processed
            var root = tree.DocumentElement;

            var type = BSML.GetTopLevelElementDef(root.LocalName);

            var state = new ParseState {
                Ref = null, Type = null
            };

            return(MakeElement(root, type, state));
        }
        // Text elements have their own IElement type
        internal IEnumerable <Element> ReadTree(IEnumerable <XmlNode> nodes, ParseState state)
        {
            foreach (var node in nodes)
            {
                if (node is XmlText text)
                {
                    var el = Activator.CreateInstance(BSML.TextElementType.Type) as TextElement;
                    el.Initialize(text, BSML.TextElementType.State);
                    yield return(el);
                }
                else if (node is XmlElement elem)
                {
                    if (Attribute.IsElementAttribute(elem))
                    {
                        continue;
                    }

                    var ns   = elem.NamespaceURI;
                    var name = elem.LocalName;

                    var type = BSML.GetCustomElementDef(ns, name);

                    if (type == default)
                    {
                        Logger.log.Warn($"Could not find element type {ns} {name}; ignoring");
                        continue;
                    }

                    yield return(MakeElement(elem, type, state));
                }
                else
                {
                    Logger.log.Warn($"Unknown node type {node.GetType()}");
                }
            }
        }