使用C#的元素呢

使用C#的元素呢

本文介绍了如何解析XSD获得来自以下信息; XSD:简单类型>使用C#的元素呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个复杂类型和简单类型(如下所示的文件的一部分)的XSD。我需要这个文件,从每一个在复杂类型中引用的simpletypes获取最大长度解析。任何人都可以请扔在如何实现这一一些建议吗?我需要实现这一种通用的方式,所以如果我的Setup_Type查询它应该给下面的输出。谢谢!



NewSetup /金额= 12(这个名字从嵌套简单类型由/和最大长度分离元素标记属性)



NewSetup /名称= 50

 < XSD:复杂类型名称=Setup_Type> 
< XSD:序列>
< XSD:元素名称=NewSetupTYPE =NewSetup_Type的minOccurs =1的maxOccurs =1/>
< / XSD:序列>
< /为xsd:复杂类型>

< XSD:复杂类型名称=NewSetup_Type>
< XSD:序列>
< XSD:元素名称=金额TYPE =Amount_Type的minOccurs =1的maxOccurs =1/>
< XSD:元素名称=名称TYPE =Name_Type的minOccurs =1的maxOccurs =1/>
< / XSD:序列>
< /为xsd:复杂类型>

< XSD:简单类型名称=Amount_Type>
< XSD:注释>
< XSD:文件>度< / XSD:文件>
< / XSD:注释>
< XSD:限制基地=XSD:字符串>
< XSD:最大长度值=12/>
< / XSD:限制>
< / XSD:简单类型>

< XSD:简单类型名称=Name_Type>
< XSD:注释>
< XSD:文件>名称和LT; / XSD:文件>
< / XSD:注释>
< XSD:限制基地=XSD:字符串>
< XSD:最大长度值=50/>
< / XSD:限制>
< / XSD:简单类型>


解决方案

我已经看到过去问类似的问题(全披露,我已经提出类似我自己)。解析XSD不是为微弱的心脏。



您基本上具有2个选择,首先是更容易实现,但可以通过较小的改动XSD更容易破裂。第二个是一个更强大,但很难实施



选项1:



解析与LINQ的XSD(或其他C#XML解析器,如果你喜欢)。由于一个XSD只是一个XML,你可以将其加载到的XDocument ,只是通过LINQ阅读。



对于只是你自己的XSD的样本:

 < XSD:简单类型名称=Amount_Type> 
< XSD:注释>
< XSD:文件>度< / XSD:文件>
< / XSD:注释>
< XSD:限制基地=XSD:字符串>
< XSD:最大长度值=12/>
< / XSD:限制>
< / XSD:简单类型>

您可以访问最大长度:

  XDOC VAR = XDocument.Load(你的XSD路径); 
VAR NS = XNamespace.Get(@http://www.w3.org/2001/XMLSchema);

VAR长度=(从STYPE在xDoc.Element(NS +模式)。元素(NS +的simpleType)
其中sType.Attribute(名称)。值= =Amount_Type$ b $从R b在sType.Elements(NS +限购)
选择r.Element(NS +最大长度)。属性(值)
.value的) .FirstOrDefault();

这不通过类型名称解析提供一个非常简单的方法,特别是对于扩展类型。要使用这一点,你需要了解你正在寻找每个元素的确切路径



选项2:



这是一个快速的答案太复杂的(注:参见编辑下面的 - 我有一些时间放在一起工作解决方案)的,所以我要鼓励你看看我自己的问题我上面链接。在这里面,我挂一个展示了如何认真分解XSD成片,并可能允许你执行你想要搜索的类型。你必须决定是否值得发展它的努力(的博客显示了的XmlReader 其中包含对问题的XSD验证一个XML的实现,但你可以。通过直接加载XSD和分析很容易做到这一点。



2键想法在博客中找到如下:

  //在getRestriction方法(读者在这方面是一个`XmlReader`是
//包含在正在验证对特定XSD
如果一个XML (reader.SchemaInfo.SchemaElement == NULL)返回NULL;
=简单类型为reader.SchemaInfo.SchemaElement.ElementSchemaType XmlSchemaSimpleType;
如果(简单类型== NULL)返回NULL;
=限制的simpleType .Content作为XmlSchemaSimpleTypeRestriction;

//然后在getMaxLength方法
如果(限制== NULL)返回NULL;
名单< INT>结果=新的List< INT>( );
的foreach(在restriction.Facets XmlSchemaObject面){
如果(方面是XmlSchemaMaxLengthFacet)result.Add(int.Parse(((XmlSchemaFacet)面).value的));



其实,我尝试过同样的事情,去年来解析XSD作为一个复杂的数据验证方法的一部分。我花了更好的一部分一周要真正了解发生了什么事的,以适应在博客的方式,以适应我的目的。这无疑是实现正是你想要的最好的方式。



如果你想用一个独立的架构试试这个,您可以加载XSD到的XmlSchemaSet 对象,然后使用 GlobalTypes 属性来帮助您找到您正在寻找的特定类型。






编辑:
我把我的旧代码,并开始组建的代码,以帮助您



第一加载架构:

 的XmlSchemaSet设置; //这需要将下面的方法,
//所以应使用(VAR FS =新的FileStream类级别字段或属性

(@在这里你的道路通达, FileMode.Open)
{
VAR模式= XmlSchema.Read(FS,NULL);

组=新的XmlSchemaSet();
set.Add(架构) ;
set.Compile();
}

下面的方法应该给你接近你想要根据您所提供的XSD的东西。它应该是相当适用于处理更复杂的结构。

 公开字典<字符串,整数> GetElementMaxLength(字符串xsdElementName)
{
如果(xsdElementName == NULL)抛出新的ArgumentException();
//如果你的XSD有一个目标命名空间,则需要更换空的命名空间名称
变种的qname =新XmlQualifiedName(xsdElementName,NULL);

//找到你的XmlSchemaSet
变种想要的类型ParentType的= set.GlobalTypes [ qname的];

//调用GetAllMaxLength与ParentType的为参数
VAR的结果= GetAllMaxLength(ParentType的);

返回结果;
}

私人字典<字符串,整数> GetAllMaxLength(XmlSchemaObject OBJ)
{
&字典LT;字符串,整数>字典=新词典<字符串,整数>();

//做一些类型的XmlSchemaObject
检查,如果(obj是XmlSchemaSimpleType)
{
//如果它是一个简单的类型,然后调用GetMaxLength得到在最大字段长度限制
变种ST = OBJ为XmlSchemaSimpleType;
字典[st.QualifiedName.Name] = GetMaxLength(ST);
}
,否则如果(obj是XmlSchemaComplexType)
{

//如果obj是一个复杂类型,铸就粒子类型序列
//和重复序列
//警告 - 如果它不是一个序列,这将失败,因此您可能需要
//做一些调整,如果你有一个比其他XS东西:序列
VAR克拉= OBJ为XmlSchemaComplexType;
无功序列= ct.ContentTypeParticle为XmlSchemaSequence;

的foreach(在seq.Items VAR项)
{
//项目将是一个XmlSchemaObject,所以就称这种同样的方法
//与项作为参数解析出来
VAR RNG = GetAllMaxLength(项目);
$ B $B∥加上结果到词典
的foreach(在RNG变种KVP)
{
字典[kvp.Key] = kvp.Value;
}
}
}
,否则如果(obj是XmlSchemaElement)
{
//如果obj是一个XmlSchemaElement时,你需要找的类型
//基于所述SchemaTypeName属性。这就是为什么你的
// XmlSchemaSet中需要有类级别范围
VAR ELE = OBJ为XmlSchemaElement;
变种类型= set.GlobalTypes [ele.SchemaTypeName]

//一旦你的类型,再调用此方法并获得字典结果
VAR RNG = GetAllMaxLength(类型);

//把结果本词典。这里的差异是字典
//密钥放在指定
的foreach(在RNG变种KVP)
{
字典的格式[的String.Format({0} / {1},ele.QualifiedName.Name,kvp.Key)] = kvp.Value;
}
}

返回字典;
}

私人的Int32 GetMaxLength(XmlSchemaSimpleType xsdSimpleType)
{
//获取简单类型
变种限制= xsdSimpleType.Content作为XmlSchemaSimpleTypeRestriction的内容;

//如果是null,则没有任何限制,并返回-1作为一个标记值
如果(限制== NULL)返回-1;

的Int32结果= -1;

//迭代的限制方面,寻找一个MaxLengthFacet和分析价值
的foreach(在restriction.Facets XmlSchemaObject面)
{
如果(面是XmlSchemaMaxLengthFacet)
{
结果= int.Parse(((XmlSchemaFacet)面)。价值);
中断;
}
}

返回结果;
}



然后,使用非常简单,你只需要调用 GetElementMaxLength(字符串)方法,它会返回你提供的值作为最大长度,格式为名字的字典:

  VAR的结果= GetElementMaxLength(Setup_Type); 

的foreach(在结果VAR项)
{
Console.WriteLine({0} | {1},item.Key,item.Value);
}


I have an XSD with multiple complex types and simple types (part of the file shown below). I need to parse this document to get maxLength from each of the simpletypes that are referenced in the complex types. Can anyone please throw some advice on how to implement this? I need to implement this in a generic way so if I query on "Setup_Type" it should give the below output. Thank you!

NewSetup/Amount = 12 (The name attributes from element tags separated by "/" and maxLength from the nested simpleType)

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>
解决方案

I have seen similar questions asked in the past (full disclosure, I've ask a similar question myself). Parsing an XSD is not for the faint of heart.

You basically have 2 options, first is easier to implement, but can be broken more easily by minor changes to the XSD. the 2nd is a more robust but hard to implement.

Option 1:

Parsing the XSD with LINQ (or other C# XML parser if you prefer). Since an XSD is just an XML, you can load it into an XDocument and just read it via LINQ.

For just a sample of your own 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>

You can access the 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();

This does not offer a very easy method for parsing by type name, especially for extended types. To use this you need to know the exact path for each element you are looking for.

Option 2:

This is far too complex for a quick answer (note: see the edit below - I had some time and put together a working solution), so I am going to encourage you to look at my own question I linked above. In it, I linked a great blog that shows how to seriously break down the XSD into pieces and might allow you to perform the type of search you want. You have to decide if it is worth the effort to develop it (the blog shows an implementation with XmlReader that contains an XML that is validated against the XSD in question, but you can easily accomplish this by directly loading the XSD and parsing it.

2 key idea to find in the blog are:

// 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));

I actually tried the same thing last year to parse an XSD as part of a complicated data validation method. It took me the better part of a week to really understand what was happening an to adapt the methods in the blog to suit my purposes. It is definitely the best way to implement exactly what you want.

If you want to try this with a standalone schema, you can load the XSD into an XmlSchemaSet object, then use the GlobalTypes property to help you find the specific type you are looking for.


EDIT:I pulled up my old code and started putting together the code to help you.

First to load your schema:

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

The following methods should give you close to what you want based on the XSD you provided. It should be pretty adaptable to deal with more complex structures.

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

Then the usage is pretty simple, you just need to call the GetElementMaxLength(String) method and it will return a dictionary of the names in the format you provided with the value as the max length:

var results = GetElementMaxLength("Setup_Type");

foreach (var item in results)
{
    Console.WriteLine("{0} | {1}", item.Key, item.Value);
}

这篇关于如何解析XSD获得来自以下信息; XSD:简单类型&GT;使用C#的元素呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-30 08:08