从 C# 中的 xml 模式获取复杂对象标签名称
Get the complex object tag name from xml schema in C#
我想问一下是否有办法获取与给定 "complex type name"(来自 XSD(XML 架构定义)中的复杂对象)关联的标签名称C#(.NET Framework 4.5)。
我想要达到的结果是:如果我搜索 WhateverTypeName1
,应该返回值 "childoftypeone"
。
假设我们有以下 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>
从 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));
问题是,从这个 XmlSchemaComplexType
对象,我没有设法将它与 ParentType
(<xs:element name="childoftypeone" type="WhateverTypeName1"/>
) 上的 "childoftypeone"
标记声明相匹配。
如果我搜索它的父对象 (ParentType
) 并遍历它的 Particle
属性,我只能设法得到这个配对。但是,我想不可能从它自己的 XmlSchemaComplexType
中获得这种类型的使用位置(例如 ParentType
)
我怎样才能做到这一点?
最后,我开发了一种递归搜索方法来获得我需要的东西,因为我没能在 System.Xml
命名空间内找到任何接近我的东西的东西'已经实现了。
这是一个相当 basic/unoptimized 的代码,我没有对其进行广泛的测试,但它确实有效。它 returns 一个 Dictionary<string, HashSet<string>>
其中键是 XSD 文件中类型的名称(这是 class 来自 XSD.exe
生成的 .cs 文件的名称以及)和使用这些类型的标签。
如下:
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;
}
我想问一下是否有办法获取与给定 "complex type name"(来自 XSD(XML 架构定义)中的复杂对象)关联的标签名称C#(.NET Framework 4.5)。
我想要达到的结果是:如果我搜索 WhateverTypeName1
,应该返回值 "childoftypeone"
。
假设我们有以下 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>
从 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));
问题是,从这个 XmlSchemaComplexType
对象,我没有设法将它与 ParentType
(<xs:element name="childoftypeone" type="WhateverTypeName1"/>
) 上的 "childoftypeone"
标记声明相匹配。
如果我搜索它的父对象 (ParentType
) 并遍历它的 Particle
属性,我只能设法得到这个配对。但是,我想不可能从它自己的 XmlSchemaComplexType
ParentType
)
我怎样才能做到这一点?
最后,我开发了一种递归搜索方法来获得我需要的东西,因为我没能在 System.Xml
命名空间内找到任何接近我的东西的东西'已经实现了。
这是一个相当 basic/unoptimized 的代码,我没有对其进行广泛的测试,但它确实有效。它 returns 一个 Dictionary<string, HashSet<string>>
其中键是 XSD 文件中类型的名称(这是 class 来自 XSD.exe
生成的 .cs 文件的名称以及)和使用这些类型的标签。
如下:
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;
}