【问题标题】:How to get maxlength/pattern value of a simpleType in an XSD如何在 XSD 中获取 simpleType 的最大长度/模式值
【发布时间】:2019-06-28 15:08:26
【问题描述】:

我想遍历一个 xsd 以获取每个属性的类型,然后获取该类型的值,但我只能检索类型。

到目前为止,我已经成功通过递归遍历了xsd树

private int GetFieldMaxLengthValue(XmlSchemaObject element)
        {
            if(element is XmlSchemaComplexType)
            {
                var complextType = element as XmlSchemaComplexType;

                if(complextType.Particle == null)
                {
                    var attributes = complextType.Attributes;

                    foreach (var attribute in attributes)
                    {
                        var schemaAttribute = attribute as XmlSchemaAttribute;
                        var attributeSchemaType = schemaAttribute.SchemaTypeName.Name;


                    }
                }
                else
                {
                    GetFieldMaxLengthValue(complextType.Particle);
                }
            }
            else if(element is XmlSchemaSequence)
            {
                var sequence = element as XmlSchemaSequence;

                foreach (XmlSchemaObject item in sequence.Items)
                {
                    var schemaType = item as XmlSchemaElement;
                    GetFieldMaxLengthValue(schemaType.SchemaType);
                }
            }
            return 0;
        }

这是我要检索的 simpleType 的值(maxLength):

 <xs:simpleType name="String100">
    <xs:restriction base="xs:string">
      <xs:maxLength value="100" />
    </xs:restriction>
  </xs:simpleType>

我需要获取值 100 并将其保存在变量中以备后用。

在我提供的代码中,查看第一个 foreach 循环。一旦我们到达一个没有其他子作为 complexTypes 的 complexType,我们就到了那里。所以我们已经到达了最后一个带有唯一子 xs:attributes 的 complexType。现在,当我转换属性时,我可以检索名称和类型。但我需要的是从代码片段中最后提供的约束中收集类型的值。

P.S我知道我可以将类型的名称“string100”并将其子串化以获取 100 并将其解析为 int,但如果不是这种情况怎么办?

【问题讨论】:

    标签: c# xml recursion


    【解决方案1】:

    我使用了一个不同的大型架构,并使用 xml linq 递归地将 xsd 解析为树结构。请参阅下面的解决方案

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ParseSchema
    {
        class Program
        {
            const string FILENAME = @"c:\temp\test.xsd";
            static void Main(string[] args)
            {
                XDocument doc = XDocument.Load(FILENAME);
                XElement root = doc.Root;
                XNamespace ns = root.GetNamespaceOfPrefix("xs");
    
                Element element = new Element(null, root, ns, null);
                SimpleContent.LinkParents();
                Element.LinkParents();
    
            }
        }
        public class Element
        {
            public static List<Element> elements = new List<Element>();  // needed to link to parent
    
            public XNamespace ns { get; set; }
            SchemaType schemaType { get; set; }
            public Dictionary<string, object> typeDictionary = null;
            public Dictionary<string, string> attributeDictionary = null;
            public Element parent { get; set; }
            public string annotation { get; set; }
    
            public Element(SchemaType parentSchema, XElement parentXElement, XNamespace ns, Element parentElement)
            {
                XElement xAnnotation;
                XElement xElement;
    
                this.parent = parentElement;
                this.ns = ns;
                Element.elements.Add(this);
    
    
                List<XElement> xTypes = parentXElement.Elements().Where(x => (x.Name.LocalName == "simpleType") | (x.Name.LocalName == "complexType")).ToList();
    
                foreach (XElement xType in xTypes)
                {
                    string name = (string)xType.Attribute("name");
                    if (typeDictionary == null) typeDictionary = new Dictionary<string, object>();
    
                    SchemaType newType = new SchemaType(xType, ns, this);
                    typeDictionary.Add(name, newType);
                }
    
                xElement = parentXElement.Element(ns + "element");
                attributeDictionary = xElement.Attributes()
                    .GroupBy(x => x.Name.LocalName, y => (string)y)
                    .ToDictionary(x => x.Key, y => y.FirstOrDefault());
    
                xAnnotation = xElement.Element(ns + "annotation");
                if (annotation != null) annotation = (string)xAnnotation.Element(ns + "documentation");
    
            }
            public static void LinkParents()
            {
                foreach (Element element in elements)
                {
                    string stringType = "";
    
                    Boolean foundAttributeType = element.attributeDictionary.TryGetValue("type", out stringType);
                    if (foundAttributeType && !stringType.StartsWith("xs:"))
                    {
                        Element parent = element;
                        object obj = null;
                        while (parent != null)
                        {
                            if (parent.typeDictionary != null)
                            {
                                Boolean foundType = parent.typeDictionary.TryGetValue(stringType, out obj);
                                if (foundType)
                                {
                                    element.schemaType = (SchemaType)obj;
                                    break;
                                }
                            }
                            parent = parent.parent;
                        }
                    }
                }
            }
    
    
        }
        public class SchemaType
        {
            public string name { get; set; }
            public string simpleComplex { get; set; }
            public string annotation { get; set; }
            public List<Attribute> attributes { get; set; }
            public Restrictions restriction { get; set; }
            public SimpleContent simpleContent { get; set; }
            public Element parentElement { get; set; }
            public List<Element> elements { get; set; }
    
            public SchemaType(XElement schemaType, XNamespace ns, Element parentElement)
            {
                simpleComplex = schemaType.Name.LocalName;
    
                foreach (XElement child in schemaType.Elements())
                {
                    switch (child.Name.LocalName)
                    {
                        case "annotation":
                            annotation = (string)child.Element(ns + "documentation");
                            break;
                        case "attribute":
                            Attribute newAttribute = new Attribute(child, ns, parentElement);
                            if (attributes == null) attributes = new List<Attribute>();
                            attributes.Add(newAttribute);
                            break;
                        case "restriction":
                            restriction = new Restrictions(child, ns);
                            break;
                        case "sequence":
                            elements = child.Elements(ns + "element").Select(x => new Element(this, child, ns, parentElement)).ToList();
                            break;
                        case "simpleContent" :
                            simpleContent = new SimpleContent(child, ns, parentElement);
                            break;
                        default:
                            break;
                    }
                }
    
            }
    
        }
        public class Restrictions
        {
            string baseType { get; set; }
            Dictionary<string, List<string>> enumerations { get; set; }
    
            public Restrictions(XElement xRestriction, XNamespace ns)
            {
                baseType = (string)xRestriction.Attribute("base");
                enumerations = xRestriction.Elements()
                    .GroupBy(x => x.Name.LocalName, y => (string)y.Attribute("value"))
                    .ToDictionary(x => x.Key, y => y.ToList());
            }
        }
        public class Attribute
        {
            public Dictionary<string, string> attributeDictionary;
            public string annotation { get; set; }
            public SchemaType schemaType { get; set; }
    
            public Attribute(XElement attribute, XNamespace ns, Element parentElement)
            {
                attributeDictionary = attribute.Attributes()
                    .GroupBy(x => x.Name.LocalName, y => (string)y)
                    .ToDictionary(x => x.Key, y => y.FirstOrDefault());
    
                XElement xAnnotation = attribute.Element(ns + "annotation");
                if (annotation != null) annotation = (string)xAnnotation.Element(ns + "documentation");
    
                List<XElement> xSchemaType = attribute.Elements().Where(x => (x.Name.LocalName == "simpleType") | (x.Name.LocalName == "complexType")).ToList();
                if(xSchemaType.Count > 0) schemaType = new SchemaType(xSchemaType.FirstOrDefault(), ns, parentElement);
    
            }
        }
        public class SimpleContent
        {
            public static List<SimpleContent> contents = new List<SimpleContent>();  // needed to link to parent
            public string baseType { get; set; }
            public List<Attribute> attributes { get; set; }
            public SchemaType schemaType { get; set; }
            public Element parentElement { get; set; }
    
            public SimpleContent(XElement content, XNamespace ns, Element parentElement)
            {
                this.parentElement = parentElement;
                contents.Add(this);
                XElement extension = content.Element(ns + "extension");
                if (extension != null)
                {
                    baseType = (string)extension.Attribute("base");
                    List<XElement> xAttributes = extension.Elements(ns + "attribute").ToList();
                    foreach (XElement xAttribute in xAttributes)
                    {
                        if (attributes == null) attributes = new List<Attribute>();
                        Attribute newAttribute = new Attribute(xAttribute, ns, parentElement);
                        attributes.Add(newAttribute);
                    }
                }
    
            }
            public static void LinkParents()
            {
                foreach (SimpleContent content in contents)
                {
                    if (!content.baseType.StartsWith("xs:"))
                    {
                        Element parent = content.parentElement;
                        object obj = null;
                        while (parent != null)
                        {
                            Boolean foundType = parent.typeDictionary.TryGetValue(content.baseType, out obj);
                            if (foundType)
                            {
                                content.schemaType = (SchemaType)obj;
                            }
                            parent = parent.parent;
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢!我会试试看!我的技术负责人也建议我做类似的事情!我会在完成后对这篇文章进行反馈!
    【解决方案2】:

    这一直可用,看起来很简单:

    using (XmlReader schemaReader = XmlReader.Create(new StringReader(the_schema_as_string)))
            {
                XmlSchemaSet schemaSet = new XmlSchemaSet();
                schemaSet.Add(XmlSchema.Read(schemaReader, null));
    
                var xsdAsXDoc = XDocument.Load(new StringReader(the_schema_as_string));
                var ns = XNamespace.Get(@"http://www.w3.org/2001/XMLSchema");
    
                foreach (XmlSchemaElement element in schemaSet.Schemas()
                    .Cast<XmlSchema>()
                    .SelectMany(s => s.Elements.Values.Cast<XmlSchemaElement>()))
                {
                    GetFieldMaxLengthValue(element, xsdAsXDoc, ns);
                }
            }
    

    您从 foreach 检索的元素有一个属性“父”,当您从那里单击父元素时,您可以找到整个类型。在我被直接卡在根元素之前,我应该一直到父元素并从那里搜索简单类型!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-15
      • 2021-06-18
      • 2023-01-23
      • 2014-08-30
      • 2011-12-04
      • 1970-01-01
      • 2019-11-02
      相关资源
      最近更新 更多