From 6a24996a2e831cfe402398af65b31fb1ecd575a9 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 22 Apr 2021 16:36:39 -0700 Subject: Move WixBuildTools into internal --- src/internal/WixBuildTools.XsdGen/CodeDomReader.cs | 159 +++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/internal/WixBuildTools.XsdGen/CodeDomReader.cs (limited to 'src/internal/WixBuildTools.XsdGen/CodeDomReader.cs') diff --git a/src/internal/WixBuildTools.XsdGen/CodeDomReader.cs b/src/internal/WixBuildTools.XsdGen/CodeDomReader.cs new file mode 100644 index 00000000..5198f264 --- /dev/null +++ b/src/internal/WixBuildTools.XsdGen/CodeDomReader.cs @@ -0,0 +1,159 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Serialize +{ + using System; + using System.Collections; + using System.Reflection; + using System.Xml; + + /// + /// Class used for reading XML files in to the CodeDom. + /// + public class CodeDomReader + { + private Assembly[] assemblies; + + /// + /// Creates a new CodeDomReader, using the current assembly. + /// + public CodeDomReader() + { + this.assemblies = new Assembly[] { Assembly.GetExecutingAssembly() }; + } + + /// + /// Creates a new CodeDomReader, and takes in a list of assemblies in which to + /// look for elements. + /// + /// Assemblies in which to look for types that correspond + /// to elements. + public CodeDomReader(Assembly[] assemblies) + { + this.assemblies = assemblies; + } + + /// + /// Loads an XML file into a strongly-typed code dom. + /// + /// File to load into the code dom. + /// The strongly-typed object at the root of the tree. + public ISchemaElement Load(string filePath) + { + XmlDocument document = new XmlDocument(); + document.Load(filePath); + ISchemaElement schemaElement = null; + + foreach (XmlNode node in document.ChildNodes) + { + XmlElement element = node as XmlElement; + if (element != null) + { + if (schemaElement != null) + { + throw new InvalidOperationException("Multiple root elements found in file."); + } + + schemaElement = this.CreateObjectFromElement(element); + this.ParseObjectFromElement(schemaElement, element); + } + } + return schemaElement; + } + + /// + /// Parses an ISchemaElement from the XmlElement. + /// + /// ISchemaElement to fill in. + /// XmlElement to parse from. + private void ParseObjectFromElement(ISchemaElement schemaElement, XmlElement element) + { + foreach (XmlAttribute attribute in element.Attributes) + { + this.SetAttributeOnObject(schemaElement, attribute.LocalName, attribute.Value); + } + + foreach (XmlNode node in element.ChildNodes) + { + XmlElement childElement = node as XmlElement; + if (childElement != null) + { + ISchemaElement childSchemaElement = null; + ICreateChildren createChildren = schemaElement as ICreateChildren; + if (createChildren == null) + { + throw new InvalidOperationException("ISchemaElement with name " + element.LocalName + " does not implement ICreateChildren."); + } + else + { + childSchemaElement = createChildren.CreateChild(childElement.LocalName); + } + + if (childSchemaElement == null) + { + childSchemaElement = this.CreateObjectFromElement(childElement); + if (childSchemaElement == null) + { + throw new InvalidOperationException("XmlElement with name " + childElement.LocalName + " does not have a corresponding ISchemaElement."); + } + } + + this.ParseObjectFromElement(childSchemaElement, childElement); + IParentElement parentElement = (IParentElement)schemaElement; + parentElement.AddChild(childSchemaElement); + } + else + { + XmlText childText = node as XmlText; + if (childText != null) + { + this.SetAttributeOnObject(schemaElement, "Content", childText.Value); + } + } + } + } + + /// + /// Sets an attribute on an ISchemaElement. + /// + /// Schema element to set attribute on. + /// Name of the attribute to set. + /// Value to set on the attribute. + private void SetAttributeOnObject(ISchemaElement schemaElement, string name, string value) + { + ISetAttributes setAttributes = schemaElement as ISetAttributes; + if (setAttributes == null) + { + throw new InvalidOperationException("ISchemaElement with name " + + schemaElement.GetType().FullName.ToString() + + " does not implement ISetAttributes."); + } + else + { + setAttributes.SetAttribute(name, value); + } + } + + /// + /// Creates an object from an XML element by digging through the assembly list. + /// + /// XML Element to create an ISchemaElement from. + /// A constructed ISchemaElement. + private ISchemaElement CreateObjectFromElement(XmlElement element) + { + ISchemaElement schemaElement = null; + foreach (Assembly assembly in this.assemblies) + { + foreach (Type type in assembly.GetTypes()) + { + if (type.FullName.EndsWith(element.LocalName) + && typeof(ISchemaElement).IsAssignableFrom(type)) + { + schemaElement = (ISchemaElement)Activator.CreateInstance(type); + } + } + } + return schemaElement; + } + } +} -- cgit v1.2.3-55-g6feb