I would like to ask if there's a way to get the tag names associated to a given "complex type name" (from complex object inside a XSD (XML Schema Definition)) in C# (.NET Framework 4.5).
The result I would like to achieve is: If I search for WhateverTypeName1
the value "childoftypeone"
should be returned.
Let's say that we have the following XSD excerpt:
<xs:complexType name="ParentType">
<xs:choice>
<xs:element name="childoftypeone" type="WhateverTypeName1"/>
<xs:element name="childoftypetwo" type="OtherTypeName"/>
</xs:choice>
</xs:complexType>
<!-- after some declarations -->
<xs:complexType name="WhateverTypeName1">
<xs:sequence>
<!-- other elements from sequence -->
</xs:sequence>
</xs:complexType>
From the XmlSchema
type, I can get a XmlSchemaComplexObject
by searching for WhateverTypeName1
this way:
var schema = new XmlSchema(); // load the XSD here.
var arr = new string[] { "WhateverTypeName1" };
var type = schema.Items
.OfType<XmlSchemaObject>()
// we can search matching the type here, put this way just to be concise
.Where(w => w.GetType().Name.ToLower().Contains("complex"))
.Select(s => (XmlSchemaComplexType)s)
.FirstOrDefault(w => arr.Contains(w.Name));
The thing is, from this XmlSchemaComplexType
object, I didn't manage to match it with the "childoftypeone"
tag declaration on the ParentType
( <xs:element name="childoftypeone" type="WhateverTypeName1"/>
).
I only managed to get this pairing, if I search for its parent object ( ParentType
) and walk through its Particle
property. However, I guess it's not possible to get where this type is being used (eg the ParentType
) from its own XmlSchemaComplexType
How could I accomplish this?
In the end, I developed a kind of a recursive search method to get what I needed, since I didn't manage to find anything inside of System.Xml
namespace that would give me anything near what I've achieved.
It's a quite basic/unoptimized code, and I didn't test it extensively, but it works. It returns a Dictionary<string, HashSet<string>>
where the keys are names of the types inside the XSD file (which are the class names from the .cs file generated by XSD.exe
as well) and the tags where these types are used.
Here it follows:
public Dictionary<string, HashSet<string>> GetTagsByType(
ICollection<XmlSchemaObject> schemaObjects)
{
var result = new Dictionary<string, HashSet<string>>();
var xmlElements = schemaObjects
.Where(w => w.GetType() == typeof(XmlSchemaElement))
.ToArray();
var types = schemaObjects
.Where(w => w.GetType() == typeof(XmlSchemaComplexType))
.ToArray();
foreach (var item in xmlElements)
{
var el = (XmlSchemaElement)item;
if (string.IsNullOrEmpty(el.Name) ||
el.SchemaTypeName == null ||
string.IsNullOrEmpty(el.SchemaTypeName.Name))
{
continue;
}
if (!result.ContainsKey(el.SchemaTypeName.Name))
{
result.Add(el.SchemaTypeName.Name, new HashSet<string> { el.Name });
}
else
{
result[el.SchemaTypeName.Name].Add(el.Name);
}
}
foreach (var type in types)
{
var t = (XmlSchemaComplexType)type;
if (t.Particle == null)
{
continue;
}
var isSubClassOfGroupBase = t.Particle.GetType()
.IsSubclassOf(typeof(XmlSchemaGroupBase));
if (!isSubClassOfGroupBase)
{
continue;
}
var items = ((XmlSchemaGroupBase)t.Particle)
.Items
.OfType<XmlSchemaObject>()
.ToArray();
var res = GetTagsByType(items);
foreach (var item in res.Keys)
{
if (result.ContainsKey(item))
{
foreach (var r in res[item])
{
result[item].Add(r);
}
}
else
{
result.Add(item, res[item]);
}
}
}
return result;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.