我有一个具有多种复杂类型和简单类型的XSD(文件的一部分如下所示).我需要解析此文档以从复杂类型中引用的每个简单类型中获取maxLength.任何人都可以请求如何实现这一点?我需要以通用的方式实现它,所以如果我查询"Setup_Type",它应该给出以下输出.谢谢!
NewSetup/Amount = 12(元素标签的名称属性由"/"和嵌套的simpleType中的maxLength分隔)
NewSetup/Name = 50
<xsd:complexType name="Setup_Type">
<xsd:sequence>
<xsd:element name="NewSetup" type="NewSetup_Type" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="NewSetup_Type">
<xsd:sequence>
<xsd:element name="Amount" type="Amount_Type" minOccurs="1" maxOccurs="1" />
<xsd:element name="Name" type="Name_Type" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="Amount_Type">
<xsd:annotation>
<xsd:documentation>Amount</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="12" />
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="Name_Type">
<xsd:annotation>
<xsd:documentation>Name</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
Run Code Online (Sandbox Code Playgroud)
psu*_*003 20
我已经看到过去提出的类似问题(完全披露,我自己也问过类似的问题).解析XSD并不适合胆小的人.
您基本上有两个选项,第一个更容易实现,但可以通过对XSD的微小更改更容易地解决.第二个是更强大但很难实现.
选项1:
使用LINQ(或其他C#XML解析器,如果您愿意)解析XSD.由于XSD只是一个XML,您可以将其加载到一个XML中,XDocument然后通过LINQ读取它.
仅为您自己的XSD示例:
<xsd:simpleType name="Amount_Type">
<xsd:annotation>
<xsd:documentation>Amount</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="12" />
</xsd:restriction>
</xsd:simpleType>
Run Code Online (Sandbox Code Playgroud)
您可以访问MaxLength:
var xDoc = XDocument.Load("your XSD path");
var ns = XNamespace.Get(@"http://www.w3.org/2001/XMLSchema");
var length = (from sType in xDoc.Element(ns + "schema").Elements(ns + "simpleType")
where sType.Attribute("name").Value == "Amount_Type"
from r in sType.Elements(ns + "restriction")
select r.Element(ns + "maxLength").Attribute("value")
.Value).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
这不提供一种非常简单的按类型名称解析的方法,特别是对于扩展类型.要使用它,您需要知道要查找的每个元素的确切路径.
选项2:
这对于快速回答来说太复杂了(注意:请参阅下面的编辑 - 我有一些时间并整理出一个有效的解决方案),所以我鼓励你看看我上面提到的我自己的问题.在其中,我链接了一个很棒的博客,该博客展示了如何将XSD严重分解为碎片并可能允许您执行所需的搜索类型.您必须决定是否值得开发它(博客显示XmlReader其中包含一个针对相关XSD验证的XML 的实现,但您可以通过直接加载XSD并解析它来轻松实现此目的.
在博客中找到的2个关键想法是:
// in the getRestriction method (reader in this context is an `XmlReader` that
// contains a XML that is being validated against the specific XSD
if (reader.SchemaInfo.SchemaElement == null) return null;
simpleType = reader.SchemaInfo.SchemaElement.ElementSchemaType as XmlSchemaSimpleType;
if (simpleType == null) return null;
restriction = simpleType.Content as XmlSchemaSimpleTypeRestriction;
// then in the getMaxLength method
if (restriction == null) return null;
List<int> result = new List<int>();
foreach (XmlSchemaObject facet in restriction.Facets) {
if (facet is XmlSchemaMaxLengthFacet) result.Add(int.Parse(((XmlSchemaFacet) facet).Value));
Run Code Online (Sandbox Code Playgroud)
我实际上去年尝试过同样的事情来解析XSD作为复杂数据验证方法的一部分.我花了一个星期的时间来真正了解正在发生的事情,以便根据我的目的调整博客中的方法.这绝对是实现您想要的最佳方式.
如果要使用独立模式尝试此操作,可以将XSD加载到XmlSchemaSet对象中,然后使用该GlobalTypes属性来帮助您查找要查找的特定类型.
编辑: 我提取了我的旧代码并开始整理代码来帮助你.
首先加载你的架构:
XmlSchemaSet set; // this needs to be accessible to the methods below,
// so should be a class level field or property
using (var fs = new FileStream(@"your path here", FileMode.Open)
{
var schema = XmlSchema.Read(fs, null);
set = new XmlSchemaSet();
set.Add(schema);
set.Compile();
}
Run Code Online (Sandbox Code Playgroud)
根据您提供的XSD,以下方法可以让您接近您想要的内容.它应该非常适合处理更复杂的结构.
public Dictionary<string, int> GetElementMaxLength(String xsdElementName)
{
if (xsdElementName == null) throw new ArgumentException();
// if your XSD has a target namespace, you need to replace null with the namespace name
var qname = new XmlQualifiedName(xsdElementName, null);
// find the type you want in the XmlSchemaSet
var parentType = set.GlobalTypes[qname];
// call GetAllMaxLength with the parentType as parameter
var results = GetAllMaxLength(parentType);
return results;
}
private Dictionary<string, int> GetAllMaxLength(XmlSchemaObject obj)
{
Dictionary<string, int> dict = new Dictionary<string, int>();
// do some type checking on the XmlSchemaObject
if (obj is XmlSchemaSimpleType)
{
// if it is a simple type, then call GetMaxLength to get the MaxLength restriction
var st = obj as XmlSchemaSimpleType;
dict[st.QualifiedName.Name] = GetMaxLength(st);
}
else if (obj is XmlSchemaComplexType)
{
// if obj is a complexType, cast the particle type to a sequence
// and iterate the sequence
// warning - this will fail if it is not a sequence, so you might need
// to make some adjustments if you have something other than a xs:sequence
var ct = obj as XmlSchemaComplexType;
var seq = ct.ContentTypeParticle as XmlSchemaSequence;
foreach (var item in seq.Items)
{
// item will be an XmlSchemaObject, so just call this same method
// with item as the parameter to parse it out
var rng = GetAllMaxLength(item);
// add the results to the dictionary
foreach (var kvp in rng)
{
dict[kvp.Key] = kvp.Value;
}
}
}
else if (obj is XmlSchemaElement)
{
// if obj is an XmlSchemaElement, the you need to find the type
// based on the SchemaTypeName property. This is why your
// XmlSchemaSet needs to have class-level scope
var ele = obj as XmlSchemaElement;
var type = set.GlobalTypes[ele.SchemaTypeName];
// once you have the type, call this method again and get the dictionary result
var rng = GetAllMaxLength(type);
// put the results in this dictionary. The difference here is the dictionary
// key is put in the format you specified
foreach (var kvp in rng)
{
dict[String.Format("{0}/{1}", ele.QualifiedName.Name, kvp.Key)] = kvp.Value;
}
}
return dict;
}
private Int32 GetMaxLength(XmlSchemaSimpleType xsdSimpleType)
{
// get the content of the simple type
var restriction = xsdSimpleType.Content as XmlSchemaSimpleTypeRestriction;
// if it is null, then there are no restrictions and return -1 as a marker value
if (restriction == null) return -1;
Int32 result = -1;
// iterate the facets in the restrictions, look for a MaxLengthFacet and parse the value
foreach (XmlSchemaObject facet in restriction.Facets)
{
if (facet is XmlSchemaMaxLengthFacet)
{
result = int.Parse(((XmlSchemaFacet)facet).Value);
break;
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
然后使用非常简单,您只需要调用该GetElementMaxLength(String)方法,它将返回您提供的格式的名称字典,其值为最大长度:
var results = GetElementMaxLength("Setup_Type");
foreach (var item in results)
{
Console.WriteLine("{0} | {1}", item.Key, item.Value);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
31484 次 |
| 最近记录: |