aboutsummaryrefslogtreecommitdiff
path: root/src/internal/WixBuildTools.XsdGen/CodeDomReader.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/WixBuildTools.XsdGen/CodeDomReader.cs')
-rw-r--r--src/internal/WixBuildTools.XsdGen/CodeDomReader.cs159
1 files changed, 159 insertions, 0 deletions
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 @@
1// 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.
2
3namespace WixToolset.Serialize
4{
5 using System;
6 using System.Collections;
7 using System.Reflection;
8 using System.Xml;
9
10 /// <summary>
11 /// Class used for reading XML files in to the CodeDom.
12 /// </summary>
13 public class CodeDomReader
14 {
15 private Assembly[] assemblies;
16
17 /// <summary>
18 /// Creates a new CodeDomReader, using the current assembly.
19 /// </summary>
20 public CodeDomReader()
21 {
22 this.assemblies = new Assembly[] { Assembly.GetExecutingAssembly() };
23 }
24
25 /// <summary>
26 /// Creates a new CodeDomReader, and takes in a list of assemblies in which to
27 /// look for elements.
28 /// </summary>
29 /// <param name="assemblies">Assemblies in which to look for types that correspond
30 /// to elements.</param>
31 public CodeDomReader(Assembly[] assemblies)
32 {
33 this.assemblies = assemblies;
34 }
35
36 /// <summary>
37 /// Loads an XML file into a strongly-typed code dom.
38 /// </summary>
39 /// <param name="filePath">File to load into the code dom.</param>
40 /// <returns>The strongly-typed object at the root of the tree.</returns>
41 public ISchemaElement Load(string filePath)
42 {
43 XmlDocument document = new XmlDocument();
44 document.Load(filePath);
45 ISchemaElement schemaElement = null;
46
47 foreach (XmlNode node in document.ChildNodes)
48 {
49 XmlElement element = node as XmlElement;
50 if (element != null)
51 {
52 if (schemaElement != null)
53 {
54 throw new InvalidOperationException("Multiple root elements found in file.");
55 }
56
57 schemaElement = this.CreateObjectFromElement(element);
58 this.ParseObjectFromElement(schemaElement, element);
59 }
60 }
61 return schemaElement;
62 }
63
64 /// <summary>
65 /// Parses an ISchemaElement from the XmlElement.
66 /// </summary>
67 /// <param name="schemaElement">ISchemaElement to fill in.</param>
68 /// <param name="element">XmlElement to parse from.</param>
69 private void ParseObjectFromElement(ISchemaElement schemaElement, XmlElement element)
70 {
71 foreach (XmlAttribute attribute in element.Attributes)
72 {
73 this.SetAttributeOnObject(schemaElement, attribute.LocalName, attribute.Value);
74 }
75
76 foreach (XmlNode node in element.ChildNodes)
77 {
78 XmlElement childElement = node as XmlElement;
79 if (childElement != null)
80 {
81 ISchemaElement childSchemaElement = null;
82 ICreateChildren createChildren = schemaElement as ICreateChildren;
83 if (createChildren == null)
84 {
85 throw new InvalidOperationException("ISchemaElement with name " + element.LocalName + " does not implement ICreateChildren.");
86 }
87 else
88 {
89 childSchemaElement = createChildren.CreateChild(childElement.LocalName);
90 }
91
92 if (childSchemaElement == null)
93 {
94 childSchemaElement = this.CreateObjectFromElement(childElement);
95 if (childSchemaElement == null)
96 {
97 throw new InvalidOperationException("XmlElement with name " + childElement.LocalName + " does not have a corresponding ISchemaElement.");
98 }
99 }
100
101 this.ParseObjectFromElement(childSchemaElement, childElement);
102 IParentElement parentElement = (IParentElement)schemaElement;
103 parentElement.AddChild(childSchemaElement);
104 }
105 else
106 {
107 XmlText childText = node as XmlText;
108 if (childText != null)
109 {
110 this.SetAttributeOnObject(schemaElement, "Content", childText.Value);
111 }
112 }
113 }
114 }
115
116 /// <summary>
117 /// Sets an attribute on an ISchemaElement.
118 /// </summary>
119 /// <param name="schemaElement">Schema element to set attribute on.</param>
120 /// <param name="name">Name of the attribute to set.</param>
121 /// <param name="value">Value to set on the attribute.</param>
122 private void SetAttributeOnObject(ISchemaElement schemaElement, string name, string value)
123 {
124 ISetAttributes setAttributes = schemaElement as ISetAttributes;
125 if (setAttributes == null)
126 {
127 throw new InvalidOperationException("ISchemaElement with name "
128 + schemaElement.GetType().FullName.ToString()
129 + " does not implement ISetAttributes.");
130 }
131 else
132 {
133 setAttributes.SetAttribute(name, value);
134 }
135 }
136
137 /// <summary>
138 /// Creates an object from an XML element by digging through the assembly list.
139 /// </summary>
140 /// <param name="element">XML Element to create an ISchemaElement from.</param>
141 /// <returns>A constructed ISchemaElement.</returns>
142 private ISchemaElement CreateObjectFromElement(XmlElement element)
143 {
144 ISchemaElement schemaElement = null;
145 foreach (Assembly assembly in this.assemblies)
146 {
147 foreach (Type type in assembly.GetTypes())
148 {
149 if (type.FullName.EndsWith(element.LocalName)
150 && typeof(ISchemaElement).IsAssignableFrom(type))
151 {
152 schemaElement = (ISchemaElement)Activator.CreateInstance(type);
153 }
154 }
155 }
156 return schemaElement;
157 }
158 }
159}