简体   繁体   中英

Get the complex object tag name from xml schema in C#

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM