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