Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# XDocument.Validate未捕获XSD的所有错误_C#_Xml_Xsd - Fatal编程技术网

C# XDocument.Validate未捕获XSD的所有错误

C# XDocument.Validate未捕获XSD的所有错误,c#,xml,xsd,C#,Xml,Xsd,我在使用C#XDocument.Validate或具有所需配置的XMLReaderSettings根据有效的XSD验证XML文档时遇到了一个非常奇怪的问题。问题是:当XML文档中存在错误时,验证过程在某些条件下无法捕获所有错误,我无法找到这种异常的模式 这是我的XSD: 似乎XmlReader在遇到第一个错误时停止元素验证。这里有一个链接,指向对旧(过时)的xmlvalidateingreader的描述: 如果一个元素报告了一个验证错误,其余的内容 该元素的模型未验证,但其子元素已验证 验证。

我在使用C#XDocument.Validate或具有所需配置的XMLReaderSettings根据有效的XSD验证XML文档时遇到了一个非常奇怪的问题。问题是:当XML文档中存在错误时,验证过程在某些条件下无法捕获所有错误,我无法找到这种异常的模式

这是我的XSD:


似乎
XmlReader
在遇到第一个错误时停止元素验证。这里有一个链接,指向对旧(过时)的
xmlvalidateingreader
的描述:

如果一个元素报告了一个验证错误,其余的内容 该元素的模型未验证,但其子元素已验证 验证。读卡器仅报告给定错误的第一个错误 元素

对于常规的
XmlReader
(尽管文档中没有明确提到它),情况似乎也是如此


在第一个示例中,错误要么在最里面的元素(例如元素的无效文本值)中,要么在最后一个子元素中,因此它们都被报告,并且没有跳过任何内容。但是,在上一个示例中,在根
Abc001
元素的开头引入了错误,因此跳过了
Abc001
内容的其余部分以及所有错误。

我编写了这段代码,它验证xml消息的每个元素,并尝试更正可以更正的内容:

        static void ValidateMessage(XDocument xDoc)
    {
        var schemas = new XmlSchemaSet();
        schemas.Add("", @"Messages_Schema.xsd");
        schemas.Compile();

        var schemaElements = (XmlSchemaElement)schemas.GlobalElements.Values.OfType<XmlSchemaObject>()
            .FirstOrDefault(e => ((XmlSchemaElement)e).Name == xDoc.Root?.Name.LocalName);

        var xmlElement =
            (XmlSchemaSequence)((XmlSchemaComplexType)schemaElements?.ElementSchemaType)?.ContentTypeParticle;

        var elementNameList = new Dictionary<string, XmlSchemaObject>();

        AddElementsInDictionary(xmlElement?.Items.OfType<XmlSchemaObject>().ToList(), elementNameList, new List<string>());

        var errorList = new List<string>();
        bool elementFixed;

        do
        {
            errorList.Clear();

            ValidateElements(xDoc.Root?.Elements().ToList(), elementNameList, schemas, new List<string>(), errorList);

            errorList.ForEach(e =>
            {
                if (!ErrorLogs.Contains(e))
                    ErrorLogs.Add(e);
            });

            elementFixed = false;

            if (XElementsToDelete.Any() || XElementsToCut.Any() || XElementsInvalid.Any())
            {
                XElementsInvalid.ForEach(xElement =>
                {
                    var xParent = xElement.Parent;
                    var xParentSchema =
                        (xParent?.GetSchemaInfo()?.SchemaType as XmlSchemaComplexType)?.ContentTypeParticle as
                        XmlSchemaSequence;

                    var elementNameLists = new List<string>();

                    AddElementsInList(xParentSchema?.Items.OfType<XmlSchemaObject>().ToList(), elementNameLists);

                    var index = elementNameLists.IndexOf(xElement.Name.LocalName);
                    if (index == 0)
                    {
                        xElement.Remove();
                        var log = $"    Move: {xElement.Name} element to the top of the sequence";
                        if (!FixLogs.Contains(log))
                            FixLogs.Add(log);

                        elementFixed = true;
                        xParent?.AddFirst(xElement);
                    }
                    else
                    {
                        var xNextElement = xElement.NextNode as XElement;
                        var indexNext = elementNameLists.IndexOf(xNextElement?.Name.LocalName);

                        if (indexNext - index > 1)
                        {
                            var xPreviousElement = xElement.PreviousNode as XElement;
                            var indexPrevious = elementNameLists.IndexOf(xPreviousElement?.Name.LocalName);

                            do
                            {
                                indexPrevious -= 1;
                                var xLastValidElement = xParent?.Element(elementNameLists[indexPrevious]);
                                if (xLastValidElement == null) continue;
                                xPreviousElement?.Remove();
                                var log = $"    Move: {xPreviousElement?.Name} element after {xLastValidElement.Name}";
                                if (!FixLogs.Contains(log))
                                    FixLogs.Add(log);

                                elementFixed = true;
                                xLastValidElement.AddAfterSelf(xPreviousElement);
                                break;

                            } while (indexPrevious > 0);
                        }
                        else
                        {
                            do
                            {
                                index -= 1;
                                var xLastValidElement = xParent?.Element(elementNameLists[index]);
                                if (xLastValidElement == null) continue;
                                xElement.Remove();
                                var log = $"    Move: {xElement.Name} element after {xLastValidElement.Name}";
                                if (!FixLogs.Contains(log))
                                    FixLogs.Add(log);

                                elementFixed = true;
                                xLastValidElement.AddAfterSelf(xElement);
                                break;

                            } while (index > 0);
                        }
                    }
                });

                XElementsToDelete.ForEach(e =>
                {
                    e.Remove();
                    var log = $"    Delete: {e.Name} element";
                    if (!FixLogs.Contains(log))
                        FixLogs.Add(log);

                    elementFixed = true;
                });

                XElementsToCut.ForEach(e =>
                {
                    var schemaType = (XmlSchemaSimpleType)e.GetSchemaInfo()?.SchemaType;
                    var restriction = (XmlSchemaSimpleTypeRestriction)schemaType?.Content;
                    var enumFacets = restriction?.Facets.OfType<XmlSchemaMaxLengthFacet>();
                    var maxLengthFacet = enumFacets?.ToList().FirstOrDefault();

                    if (maxLengthFacet != null)
                    {
                        var maxLength = int.Parse(maxLengthFacet.Value);
                        var log = $"    Cut: {e.Name} value to maxLength: {maxLength}";
                        if (!FixLogs.Contains(log))
                            FixLogs.Add(log);

                        elementFixed = true;
                        e.Value = e.Value.Substring(0, maxLength);
                    }
                });

                if (!elementFixed)
                {
                    var log = "    Cannot fix:";
                    if (!FixLogs.Contains(log))
                        FixLogs.Add(log);

                    errorList.ForEach(e =>
                    {
                        if (!FixLogs.Contains($"        {e}"))
                            FixLogs.Add($"        {e}");
                    });
                }

            }

            XElementsToDelete.Clear();
            XElementsInvalid.Clear();
            XElementsToCut.Clear();

        } while (errorList.Count > 0 && elementFixed);

        Console.WriteLine($"Validating a {xDoc.Root?.Name.LocalName}");
        Console.WriteLine("");
        ErrorLogs.ForEach(e =>
        {
            Console.WriteLine("    {0}", e);
        });

        Console.WriteLine("");
        Console.WriteLine("Fixing");
        Console.WriteLine("");
        FixLogs.ForEach(e =>
        {
            Console.WriteLine("{0}", e);
        });

        Console.WriteLine("");
        Console.WriteLine("Message {0}",
            errorList.Count > 0 ? "did not validate" : "validated");

        Console.ReadKey();
    }


    private static void AddElementsInList(IEnumerable<XmlSchemaObject> schemaObjectList,
        ICollection<string> schemaObjectKeys)
    {
        schemaObjectList.ToList().ForEach(se =>
        {
            switch (se.GetType().ToString())
            {
                case "System.Xml.Schema.XmlSchemaElement":
                    var element = se as XmlSchemaElement;

                    var name = (se as XmlSchemaElement)?.QualifiedName.Name;

                    if (!schemaObjectKeys.Contains(name))
                        schemaObjectKeys.Add(name);

                    var elementSchemaType = element?.ElementSchemaType;
                    if (elementSchemaType != null)
                        AddElementsInList(new List<XmlSchemaObject> { elementSchemaType }, schemaObjectKeys);

                    break;

                case "System.Xml.Schema.XmlSchemaComplexType":

                    break;

                case "System.Xml.Schema.XmlSchemaSequence":
                    var sequence = se as XmlSchemaSequence;

                    var sequenceItems = sequence?.Items.OfType<XmlSchemaObject>().ToList();
                    if (sequenceItems != null)
                        AddElementsInList(sequenceItems, schemaObjectKeys);

                    break;

                case "System.Xml.Schema.XmlSchemaChoice":
                    var choice = se as XmlSchemaChoice;

                    var choiceItems = choice?.Items.OfType<XmlSchemaObject>().ToList();
                    if (choiceItems != null)
                        AddElementsInList(choiceItems, schemaObjectKeys);

                    break;

                case "System.Xml.Schema.XmlSchemaGroupRef":
                    var group = se as XmlSchemaGroupRef;

                    var groupParticle = group?.Particle;
                    if (groupParticle != null)
                        AddElementsInList(new List<XmlSchemaObject> { groupParticle }, schemaObjectKeys);

                    break;
            }
        });
    }

    private static void AddElementsInDictionary(IEnumerable<XmlSchemaObject> schemaObjectList,
        IDictionary<string, XmlSchemaObject> schemaObjectDictionary, IList<string> schemaObjectDictionaryKeys)
    {
        schemaObjectList.ToList().ForEach(se =>
        {
            switch (se.GetType().ToString())
            {
                case "System.Xml.Schema.XmlSchemaElement":
                    var element = se as XmlSchemaElement;

                    schemaObjectDictionaryKeys.Add((se as XmlSchemaElement)?.QualifiedName.Name);
                    var path = string.Join("/", schemaObjectDictionaryKeys);
                    if (!schemaObjectDictionary.ContainsKey(path))
                        schemaObjectDictionary.Add(path, se);

                    var elementSchemaType = element?.ElementSchemaType;
                    if (elementSchemaType != null)
                        AddElementsInDictionary(new List<XmlSchemaObject> { elementSchemaType },
                            schemaObjectDictionary, schemaObjectDictionaryKeys);

                    if (schemaObjectDictionaryKeys.Count > 0)
                        schemaObjectDictionaryKeys.RemoveAt(schemaObjectDictionaryKeys.Count - 1);

                    break;

                case "System.Xml.Schema.XmlSchemaComplexType":
                    var complexType = se as XmlSchemaComplexType;

                    var complexTypeParticle = complexType?.ContentTypeParticle;
                    if (complexTypeParticle != null)
                        AddElementsInDictionary(new List<XmlSchemaObject> { complexTypeParticle },
                            schemaObjectDictionary, schemaObjectDictionaryKeys);

                    break;

                case "System.Xml.Schema.XmlSchemaSequence":
                    var sequence = se as XmlSchemaSequence;

                    var sequenceItems = sequence?.Items.OfType<XmlSchemaObject>().ToList();
                    if (sequenceItems != null)
                        AddElementsInDictionary(sequenceItems, schemaObjectDictionary, schemaObjectDictionaryKeys);

                    break;

                case "System.Xml.Schema.XmlSchemaChoice":
                    var choice = se as XmlSchemaChoice;

                    var choiceItems = choice?.Items.OfType<XmlSchemaObject>().ToList();
                    if (choiceItems != null)
                        AddElementsInDictionary(choiceItems, schemaObjectDictionary, schemaObjectDictionaryKeys);

                    break;

                case "System.Xml.Schema.XmlSchemaGroupRef":
                    var group = se as XmlSchemaGroupRef;

                    var groupParticle = group?.Particle;
                    if (groupParticle != null)
                        AddElementsInDictionary(new List<XmlSchemaObject> { groupParticle }, schemaObjectDictionary,
                            schemaObjectDictionaryKeys);

                    break;

            }
        });
    }

    private static void ValidateElements(List<XElement> xElementList,
        IReadOnlyDictionary<string, XmlSchemaObject> schemaObjectDictionary, XmlSchemaSet schemas,
        IList<string> schemaObjectDictionaryKeys, ICollection<string> errorList)
    {
        xElementList.ForEach(xElement =>
        {
            schemaObjectDictionaryKeys.Add(xElement.Name.LocalName);
            var path = string.Join("/", schemaObjectDictionaryKeys);

            if (schemaObjectDictionary.ContainsKey(path))
            {
                var validateObject = schemaObjectDictionary[path];

                xElement.Validate(validateObject, schemas,
                    (o, e) =>
                    {
                        if (!errorList.Contains(e.Message))
                            errorList.Add(e.Message);

                        if (e.Message.Contains("has incomplete content"))
                        {
                            if (!XElementsToDelete.Contains((XElement)o))
                                XElementsToDelete.Add((XElement)o);
                        }

                        if (e.Message.Contains("has invalid child element"))
                        {
                            if (!XElementsInvalid.Contains((XElement)o))
                                XElementsInvalid.Add((XElement)o);
                        }

                        if (e.Message.Contains("actual length is greater than the MaxLength value"))
                        {
                            if (!XElementsToCut.Contains((XElement)o))
                                XElementsToCut.Add((XElement)o);
                        }
                    }, true);

                if (xElement.HasElements)
                    ValidateElements(xElement.Elements().ToList(), schemaObjectDictionary, schemas,
                        schemaObjectDictionaryKeys, errorList);
            }
            else
            {
                var log = $"The element '{xElement.Name.LocalName}' is unknown. It should be delete.";
                if (!errorList.Contains(log))
                    errorList.Add(log);

                if (XElementsInvalid.Contains(xElement))
                    XElementsInvalid.Remove(xElement);

                if (XElementsToCut.Contains(xElement))
                    XElementsToCut.Remove(xElement);

                if (!XElementsToDelete.Contains(xElement))
                    XElementsToDelete.Add(xElement);
            }

            if (schemaObjectDictionaryKeys.Count > 0)
                schemaObjectDictionaryKeys.RemoveAt(schemaObjectDictionaryKeys.Count - 1);
        });
    }
静态无效验证消息(XDocument xDoc)
{
var schemase=new XmlSchemaSet();
Schema.Add(“,@”Messages_Schema.xsd”);
schemas.Compile();
var schemaElements=(XmlSchemaElement)schemas.GlobalElements.Values.OfType()的值
.FirstOrDefault(e=>((XmlSchemaElement)e).Name==xDoc.Root?.Name.LocalName);
var xmlElement=
(XmlSchemaSequence)((XmlSchemaComplexType)schemaElements?.ElementSchemaType)?.ContentTypeParticle;
var elementNameList=新字典();
AddElementsInDictionary(xmlElement?.Items.OfType().ToList(),elementNameList,new List());
var errorList=新列表();
布尔元素固定;
做
{
errorList.Clear();
ValidateElements(xDoc.Root?.Elements().ToList(),elementNameList,Schema,new List(),errorList);
errorList.ForEach(e=>
{
如果(!ErrorLogs.Contains(e))
错误日志。添加(e);
});
elementFixed=false;
如果(XElementsToDelete.Any()| | XElementsToCut.Any()| | XElementsToDelete.Any())
{
XElementsInvalid.ForEach(xElement=>
{
var xParent=xElement.Parent;
var xParentSchema=
(xParent?.GetSchemaInfo()?.SchemaType为XmlSchemaComplexType)?.ContentTypeParticle为
XmlSchemaSequence;
var elementNameLists=新列表();
AddElementsInList(xParentSchema?.Items.OfType().ToList(),ElementNameList);
var index=elementNameLists.IndexOf(xElement.Name.LocalName);
如果(索引==0)
{
xElement.Remove();
var log=$“将{xElement.Name}元素移动到序列的顶部”;
如果(!FixLogs.Contains(log))
添加(日志);
elementFixed=true;
xParent?.AddFirst(xElement);
}
其他的
{
var xNextElement=xElement.NextNode作为xElement;
var indexNext=elementNameLists.IndexOf(xNextElement?.Name.LocalName);
如果(索引下一步-索引>1)
{
var xPreviousElement=xElement.PreviousNode作为xElement;
var indexPrevious=elementNameLists.IndexOf(xPreviousElement?.Name.LocalName);
做
{
indexPrevious-=1;
var xLastValidElement=xParent?.Element(elementNameList[indexPrevious]);
如果(xLastValidElement==null)继续;
xPreviousElement?.Remove();
var log=$“在{xLastValidElement.Name}之后移动:{xPreviousElement?.Name}元素”;
如果(!FixLogs.Contains(log))
添加(日志);
elementFixed=true;