简体   繁体   English

从C#中的xml架构获取复杂的对象标记名称

[英]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). 我想问一下是否有办法在C#(.NET Framework 4.5)中将标记名称与给定的“复杂类型名称”(来自XSD(XML模式定义)中的复杂对象)相关联。

The result I would like to achieve is: If I search for WhateverTypeName1 the value "childoftypeone" should be returned. 我想要实现的结果是:如果我搜索WhateverTypeName1 ,则应返回值"childoftypeone"

Let's say that we have the following XSD excerpt: 假设我们有以下XSD摘录:

<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: XmlSchema类型,我可以通过以这种方式搜索WhateverTypeName1来获取XmlSchemaComplexObject

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"/> ). 关键是,从这个XmlSchemaComplexType对象,我没有设法与匹配它"childoftypeone"在标签上声明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. 如果我搜索它的父对象( ParentType )并遍历其Particle属性,我只能设法得到这个配对。 However, I guess it's not possible to get where this type is being used (eg the ParentType ) from its own XmlSchemaComplexType 但是,我想不可能从它自己的XmlSchemaComplexType获取使用此类型的位置(例如ParentType

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. 最后,我开发了一种递归搜索方法来获得我需要的东西,因为我没有设法找到System.Xml命名空间内的任何东西,它会给我任何接近我已经实现的东西。

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. 它返回一个Dictionary<string, HashSet<string>> ,其中的键是XSD文件中类型的名称(也是XSD.exe生成的.cs文件中的类名)以及这些类型的标签。用过的。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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