为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 XSD 中获取 simpleType 的最大长度/模式值

如何在 XSD 中获取 simpleType 的最大长度/模式值

C#
蓝山帝景 2023-05-14 16:09:54
我想遍历一个 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,我们就到了那里。所以我们已经到达了最后一个 complexType 及其唯一的孩子 xs:attributes。现在,当我转换属性时,我可以检索名称和类型。但我需要的是从代码段最后提供的约束中收集类型的值。PS我知道我可以采用类型的名称“string100”并将其子字符串化以获得 100 并将其解析为 int,但如果不是这种情况怎么办?
查看完整描述

2 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

我使用了不同的大模式,并使用 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;

                    }

                }

            }

        }

    }

}



查看完整回答
反对 回复 2023-05-14
?
侃侃尔雅

TA贡献1801条经验 获得超15个赞

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


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 检索的元素有一个属性“父级”,当您从那里单击父级时,您可以找到所有类型。在我直接停留在根元素之前,我一直应该去父元素并从那里搜索简单类型!


查看完整回答
反对 回复 2023-05-14
  • 2 回答
  • 0 关注
  • 125 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信