Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.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# 我可以跳过SchemaValidation失败的节点吗?_C#_.net_Xml_Validation_Xsd Validation - Fatal编程技术网

C# 我可以跳过SchemaValidation失败的节点吗?

C# 我可以跳过SchemaValidation失败的节点吗?,c#,.net,xml,validation,xsd-validation,C#,.net,Xml,Validation,Xsd Validation,对于违反xsd模式中定义的限制的节点,我有验证重新移植错误,这非常有效。我的问题是所有节点(包括导致验证错误的节点)都被传递给我进行数据导入。是否无法配置XmlReaderSettings以跳过导致验证错误的节点,或提取仅包含有效节点的集合 目前,我有一个临时解决方案,将每个节点与整个错误集合进行比较,以查看错误是否描述了与该节点对应的属性/值,如果是,则忽略该节点-这显然是一个可怕的解决方案。或者,xsd模式中的验证规则应该在代码中实现并手动维护——在这种情况下,xsd模式的大部分值都会丢失

对于违反xsd模式中定义的限制的节点,我有验证重新移植错误,这非常有效。我的问题是所有节点(包括导致验证错误的节点)都被传递给我进行数据导入。是否无法配置
XmlReaderSettings
以跳过导致验证错误的节点,或提取仅包含有效节点的集合

目前,我有一个临时解决方案,将每个节点与整个错误集合进行比较,以查看错误是否描述了与该节点对应的属性/值,如果是,则忽略该节点-这显然是一个可怕的解决方案。或者,xsd模式中的验证规则应该在代码中实现并手动维护——在这种情况下,xsd模式的大部分值都会丢失

我认为查找“sourceNode”-ish对象的明显位置是
ValidationEventHandler
params,但显然不是

我正在使用System.Xml.dll程序集,运行时版本4.0.30319

XmlSerializer

public class XmlSerializer<T> where T : class
{
    private readonly ThreadLocal<List<XmlValidationError>> _errors;

    public string Xml { get; private set; }

    public XmlReaderSettings XmlReaderSettings { get; private set; }


    public XmlSerializer(string xml, string xsdFilePath)
    {
        _errors = new ThreadLocal<List<XmlValidationError>>(() => new List<XmlValidationError>());

        Xml = xml;
        XmlReaderSettings = new XmlReaderSettings();
        XmlReaderSettings.Schemas.Add("", xsdFilePath);

        XmlReaderSettings.ValidationEventHandler += validationEventHandler;
        XmlReaderSettings.ValidationType = ValidationType.Schema;
        XmlReaderSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
    }
    private void validationEventHandler(object sender, ValidationEventArgs validationEventArgs)
    {
        _errors.Value.Add(new XmlValidationError(Xml, validationEventArgs.Message, validationEventArgs.Exception));
    }

    private void Error(Exception ex)
    {
        _errors.Value.Add(new XmlValidationError(Xml, ex.Message, ex));
    }

    public T Deserialize(out List<XmlValidationError> errors)
    {
        _errors.Value.Clear();

        T result = (null);

        try
        {
            using (var fs = new FileStream(Xml, FileMode.Open, FileAccess.Read))
            {
                using (var reader = XmlReader.Create(fs, XmlReaderSettings))
                {
                    var xmlSerializer = new XmlSerializer(typeof(T));

                    result = (T)xmlSerializer.Deserialize(reader);
                }
            }
        }
        catch (Exception ex)
        {
            _errors.Value.Add(new XmlValidationError(Xml, ex.Message, ex));
        }

        errors = new List<XmlValidationError>(_errors.Value);

        return result;
    }

    public List<XmlValidationError> Validate(T instance)
    {
        _errors.Value.Clear();

        using (var memstream = new MemoryStream())
        {
            Validate(instance, memstream);
        }

        return new List<XmlValidationError>(_errors.Value);
    }

    private void Validate(T instance, Stream stream)
    {
        if (Serialize(stream, instance))
        {
            try
            {
                stream.Seek(0, SeekOrigin.Begin);
                using (var reader = XmlReader.Create(stream, XmlReaderSettings))
                {
                    while (reader.Read())
                    {

                    }
                }
            }
            catch (Exception ex)
            {
                Error(ex);
            }
        }
    }

.... Save/Serialize code omitted
}
公共类XmlSerializer,其中T:class
{
私有只读线程本地错误;
公共字符串Xml{get;private set;}
公共XmlReaderSettings XmlReaderSettings{get;private set;}
公共XmlSerializer(字符串xml、字符串xsdFilePath)
{
_errors=newthreadlocal(()=>newlist());
Xml=Xml;
XmlReaderSettings=新的XmlReaderSettings();
XmlReaderSettings.Schemas.Add(“,xsdFilePath);
XmlReaderSettings.ValidationEventHandler+=ValidationEventHandler;
XmlReaderSettings.ValidationType=ValidationType.Schema;
XmlReaderSettings.ValidationFlags |=XmlSchemaValidationFlags.ReportValidationWarnings;
}
私有void validationEventHandler(对象发送方,ValidationEventTargs ValidationEventTargs)
{
_errors.Value.Add(新的XmlValidationError(Xml,validationEventTargets.Message,validationEventTargets.Exception));
}
私有无效错误(例外情况除外)
{
_errors.Value.Add(新的XmlValidationError(Xml,ex.Message,ex));
}
公共T反序列化(列表外错误)
{
_errors.Value.Clear();
T结果=(空);
尝试
{
使用(var fs=newfilestream(Xml,FileMode.Open,FileAccess.Read))
{
使用(var reader=XmlReader.Create(fs,XmlReaderSettings))
{
var xmlSerializer=新的xmlSerializer(typeof(T));
结果=(T)xmlSerializer.Deserialize(读取器);
}
}
}
捕获(例外情况除外)
{
_errors.Value.Add(新的XmlValidationError(Xml,ex.Message,ex));
}
错误=新列表(_errors.Value);
返回结果;
}
公共列表验证(T实例)
{
_errors.Value.Clear();
使用(var memstream=new MemoryStream())
{
验证(实例,memstream);
}
返回新列表(_errors.Value);
}
私有void验证(T实例、流)
{
if(序列化(流、实例))
{
尝试
{
stream.Seek(0,SeekOrigin.Begin);
使用(var reader=XmlReader.Create(stream,XmlReaderSettings))
{
while(reader.Read())
{
}
}
}
捕获(例外情况除外)
{
误差(ex);
}
}
}
..省略了保存/序列化代码
}
XSD模式

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="Artec-availibility">
        <xsd:annotation>
            <xsd:documentation>Stock feed</xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="Artikel" minOccurs="1" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation>Record describing stock information for a product</xsd:documentation>
                    </xsd:annotation>
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="ArtecArtikelNr">
                                <xsd:annotation>
                                    <xsd:documentation>ProductId - must be min. 8 and max. 9 characters, of '0' through '9'</xsd:documentation>
                                </xsd:annotation>
                                <xsd:simpleType>
                                    <xsd:restriction base="xsd:string">
                                        <xsd:pattern value="^[0-9]*$" />
                                        <xsd:minLength value="8"/>
                                        <xsd:maxLength value="9"/>
                                    </xsd:restriction>
                                </xsd:simpleType>
                            </xsd:element>
                            <xsd:element name="AvailabilityState">
                                <xsd:annotation>
                                    <xsd:documentation>StockAvailability</xsd:documentation>
                                </xsd:annotation>
                                <xsd:simpleType>
                                    <xsd:restriction base="xsd:int">
                                        <xsd:minInclusive value="0"/>
                                        <xsd:maxInclusive value="2"/>
                                    </xsd:restriction>
                                </xsd:simpleType>
                            </xsd:element>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

饲料
描述产品库存信息的记录
ProductId-从“0”到“9”的长度必须至少为8个字符,最多为9个字符
库存可用性
库存可用性导入作业

....
    public bool ImportStockFromXmlFile(string xmlFile)
    {
        bool anyWorkDone = false;

        string path = _fileService.StockFolderPath + "\\" + xmlFile;
        string xsdPath = _fileService.SchemasFolderPath + "\\" + "Artec-Availability.xsd";

        var serializer = new XmlSerializer<Artecavailibility>(path, xsdPath);


        List<XmlValidationError> errors;
        var feed = serializer.Deserialize(out errors);

        foreach (var xmlValidationError in errors)
        {
            _importLog.AddXMLErrorMessage(xmlValidationError.File, xmlValidationError.Message, _context);
        }

        if (feed == null)
        {
            return false;
        }

        var stocks = new List<ImportStockDto>();

        foreach (var stock in feed.Artikel)
        {
            //todo: Refactor once decided - this current solution will not scale well!
            //If errors exist for related properties, skip this node
            //Check articleNr
            if(errors.Any(e => e.Message.Contains("ArtecArtikelNr") && e.Message.Contains(stock.ArtecArtikelNr)))
                continue;
            //Check 
            if (errors.Any(e => e.Message.Contains("AvailabilityState") && e.Message.Contains(stock.AvailabilityState.ToString())))
                continue;


            //Good to go
            anyWorkDone = true;
            int productId = int.Parse(stock.ArtecArtikelNr);


            stocks.Add(new ImportStockDto()
                {
                    Id = productId,
                    Stock = stock.AvailabilityState
                });
        }

        try
        {                
            _stockImportService.ImportStock(stocks);
            for (int idx = 0; idx < stocks.Count; ++idx )
            {
                _importLog.AddOverwriteMessage(path, ImportLog.ImportContext.Stock);
            }

        }
        catch (Exception e)
        {
            //-- Failed insert products into DB
            _importLog.AddXMLErrorMessage(xmlFile, e.Message, _context);
        }

        return anyWorkDone;
    }
。。。。
公共bool ImportStockFromXmlFile(字符串xmlFile)
{
bool anyWorkDone=false;
字符串路径=\u fileService.StockFolderPath+“\\”+xmlFile;
字符串xsdPath=\u fileService.SchemasFolderPath+“\\”+“Artec Availability.xsd”;
var serializer=新的XmlSerializer(路径,xsdPath);
列出错误;
var feed=序列化程序。反序列化(输出错误);
foreach(var xmlvalidateError in errors)
{
_importLog.AddXMLErrorMessage(xmlvalidateError.File,xmlvalidateError.Message,_上下文);
}
if(feed==null)
{
返回false;
}
var stocks=新列表();
foreach(饲料中的var库存。Artikel)
{
//todo:一旦决定重构-此当前解决方案将无法很好地扩展!
//如果相关属性存在错误,请跳过此节点
//支票条款号
if(errors.Any)(e=>e.Message.Contains(“ArtecArtikelNr”)&&e.Messag