我有一个非常奇怪的问题,使用C#XDocument.Validate或XMLReaderSettings和所需的配置,针对有效的XSD验证XML文档。问题是:当XML文档中存在错误时,验证过程无法在特定条件下捕获所有错误,并且我无法找到这种异议的模式。XDocument.Validate没有捕获所有针对XSD的错误
这里是我的XSD:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
\t \t \t targetNamespace="http://www.somesite.com/somefolder/messages"
\t \t \t xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Message">
<xs:complexType>
<xs:sequence>
<xs:element name="Header">
<xs:complexType>
<xs:sequence>
<xs:element name="MessageId" type="xs:string" />
<xs:element name="MessageSource" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Body">
<xs:complexType>
<xs:sequence>
<xs:element name="Abc001">
<xs:complexType>
<xs:sequence>
<xs:element name="Abc002" type="xs:string" />
<xs:element name="Abc003" type="xs:string" minOccurs="0" />
<!--<xs:element name="Abc004" type="xs:string" />-->
<xs:element name="Abc004">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="200"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Abc005">
<xs:complexType>
<xs:sequence>
<xs:element name="Abc006" type="xs:unsignedShort" />
<xs:element name="Abc007">
<xs:complexType>
<xs:sequence>
<xs:element name="Abc008" type="xs:string"/>
<xs:element name="Abc009" type="xs:string" minOccurs="0"/>
<xs:element name="Abc010" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Abc011" type="xs:date" />
<xs:element name="Abc012">
<xs:complexType>
<xs:sequence>
<xs:element name="Abc013" type="xs:string" />
<xs:element name="Abc014" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
这里是正在验证针对该XSD的XML文档:
<?xml version="1.0" encoding="utf-8"?>
<Message xmlns="http://www.somesite.com/somefolder/messages">
\t <Header>
\t \t <MessageId>Lorem</MessageId>
\t \t <MessageSource>Ipsum</MessageSource>
\t </Header>
\t <Body>
\t \t <Abc001>
\t \t \t <Abc002>dolor</Abc002>
\t \t \t <Abc003>sit amet</Abc003>
\t \t \t <Abc004>consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</Abc004>
\t \t \t <Abc005>
\t \t \t \t <Abc006>1234</Abc006>
\t \t \t \t <Abc007>
\t \t \t \t \t <Abc008>Ut enim</Abc008>
\t \t \t \t \t <Abc009>ad</Abc009>
\t \t \t \t \t <Abc010>minim</Abc010>
\t \t \t \t </Abc007>
\t \t \t \t <Abc011>1982-10-17</Abc011>
\t \t \t \t <Abc012>
\t \t \t \t \t <Abc013>veniam</Abc013>
\t \t \t \t \t <Abc014>nostrud</Abc014>
\t \t \t \t </Abc012>
\t \t \t </Abc005>
\t \t </Abc001>
\t </Body>
</Message>
现在,当我在XML中引入一些验证错误并根据XSD验证它时,它确实发现了所有错误。这里是容易出错的XML(我已标记引入的错误在哪里):
<?xml version="1.0" encoding="utf-8"?>
<Message xmlns="http://www.somesite.com/somefolder/messages">
\t <Header>
\t \t <MessageId>Lorem</MessageId>
\t \t <MessageSource>Ipsum</MessageSource>
\t </Header>
\t <Body>
\t \t <Abc001>
\t \t \t <Abc002>dolor</Abc002>
\t \t \t <Abc003>sit amet</Abc003>
\t \t \t
\t \t \t <!--The value for Abc004 is increased beyond the allowed 200 characters-->
\t \t \t
\t \t \t <Abc004>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</Abc004>
\t \t \t <Abc005>
\t \t \t \t <Abc006>1234</Abc006>
\t \t \t \t <Abc007>
\t \t \t \t \t <Abc008>Ut enim</Abc008>
\t \t \t \t \t <ABC009>AD</ABC009>
\t \t \t \t \t
\t \t \t \t \t <!--<Abc010>minim</Abc010> Required element removed-->
\t \t \t \t </Abc007>
\t \t \t \t
\t \t \t \t <!--Date formate below is wrong-->
\t \t \t \t <Abc011>1982-10-37</Abc011>
\t \t \t \t
\t \t \t \t <Abc012>
\t \t \t \t \t <Abc013>veniam</Abc013>
\t \t \t \t \t <Abc014>nostrud</Abc014>
\t \t \t \t </Abc012>
\t \t \t </Abc005>
\t \t \t <!--the element below is not allowed-->
\t \t \t <Abc15>Not allowed</Abc15>
\t \t </Abc001>
\t </Body>
</Message>
这里是我得到的XML,显示所有错误:
<MessageResponse xmlns="http://www.somesite.com/somefolder/messages">
<Result>false</Result>
<Status>Failed</Status>
<FaultCount>4</FaultCount>
<Faults>
<Fault>
<FaultCode>ERR01</FaultCode>
<FaultMessage>The 'http://www.somesite.com/somefolder/messages:Abc004' element is invalid - The value 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' is invalid according to its datatype 'String' - The actual length is greater than the MaxLength value.</FaultMessage>
</Fault>
<Fault>
<FaultCode>ERR02</FaultCode>
<FaultMessage>The element 'Abc007' in namespace 'http://www.somesite.com/somefolder/messages' has invalid child element 'ABC009' in namespace 'http://www.somesite.com/somefolder/messages'. List of possible elements expected: 'Abc009, Abc010' in namespace 'http://www.somesite.com/somefolder/messages'.</FaultMessage>
</Fault>
<Fault>
<FaultCode>ERR03</FaultCode>
<FaultMessage>The 'http://www.somesite.com/somefolder/messages:Abc011' element is invalid - The value '1982-10-37' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:date' - The string '1982-10-37' is not a valid Date value.</FaultMessage>
</Fault>
<Fault>
<FaultCode>ERR04</FaultCode>
<FaultMessage>The element 'Abc001' in namespace 'http://www.somesite.com/somefolder/messages' has invalid child element 'Abc15' in namespace 'http://www.somesite.com/somefolder/messages'.</FaultMessage>
</Fault>
</Faults>
</MessageResponse>
这是奇怪的部分。当我在“Abc001”元素的开始处引入一个更多的错误,并且还保留所有其他现有错误时,结果完全混乱。这里是新引入的错误XML:
<?xml version="1.0" encoding="utf-8"?>
<Message xmlns="http://www.somesite.com/somefolder/messages">
\t <Header>
\t \t <MessageId>Lorem</MessageId>
\t \t <MessageSource>Ipsum</MessageSource>
\t </Header>
\t <Body>
\t \t <Abc001>
\t \t \t <!--newly introduced error - removed the following element-->
\t \t \t <!--<Abc002>dolor</Abc002>-->
\t \t \t <Abc003>sit amet</Abc003>
\t \t \t <!--The value for Abc004 is increased beyond the allowed 200 characters-->
\t \t \t <Abc004>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</Abc004>
\t \t \t <Abc005>
\t \t \t \t <Abc006>1234</Abc006>
\t \t \t \t <Abc007>
\t \t \t \t \t <Abc008>Ut enim</Abc008>
\t \t \t \t \t <ABC009>AD</ABC009>
\t \t \t \t \t <!--<Abc010>minim</Abc010>-->
\t \t \t \t </Abc007>
\t \t \t \t <Abc011>1982-10-37</Abc011>
\t \t \t \t <Abc012>
\t \t \t \t \t <Abc013>veniam</Abc013>
\t \t \t \t \t <Abc014>nostrud</Abc014>
\t \t \t \t </Abc012>
\t \t \t </Abc005>
\t \t \t <!--the element below is not allowed-->
\t \t \t <Abc15>Not allowed</Abc15>
\t \t </Abc001>
\t </Body>
</Message>
最后,这里是验证结果:
<MessageResponse xmlns="http://www.somesite.com/somefolder/messages">
<Result>false</Result>
<Status>Failed</Status>
<FaultCount>1</FaultCount>
<Faults>
<Fault>
<FaultCode>ERR01</FaultCode>
<FaultMessage>The element 'Abc001' in namespace 'http://www.somesite.com/somefolder/messages' has invalid child element 'Abc003' in namespace 'http://www.somesite.com/somefolder/messages'. List of possible elements expected: 'Abc002' in namespace 'http://www.somesite.com/somefolder/messages'.</FaultMessage>
</Fault>
</Faults>
</MessageResponse>
这里是我的C#代码我正在使用来验证:
public async Task<IMIDPreValidationAckMessage> ValidateXmlMessage(XDocument doc)
{
var result = new PreValidationAckMessage();
result.Result = true;
result.Status = "Succeeded";
var xsd = HttpContext.Current.Server.MapPath("~/message01.xsd");
try
{
var uri = new System.Uri(xsd);
var localPath = uri.LocalPath;
var docNameSpace = doc.Root.Name.Namespace.NamespaceName;
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(docNameSpace, localPath);
XmlReaderSettings xrs = new XmlReaderSettings();
xrs.ValidationType = ValidationType.Schema;
xrs.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
xrs.Schemas = schemas;
result.XSDNamespace = doc.Root.GetDefaultNamespace().NamespaceName;
var errCode = 1;
xrs.ValidationEventHandler += (s, e) =>
{
var msg = e.Message;
result.Result = false;
result.Status = "Failed";
result.FaultCount++;
result.Faults.Add(new Fault
{
FaultCode = "ERR" + errCode++.ToString().PadLeft(2, '0'),
FaultMessage = e.Message
});
};
using (XmlReader xr = XmlReader.Create(doc.CreateReader(), xrs))
{
while (xr.Read()) { }
}
}
catch (System.Exception ex)
{
result.Result = false;
result.Status = "Unknown Error";
}
return result;
}
有人能告诉我这里有什么问题吗?
将所有类都包含在最后一个片段中,这样才能复制粘贴并运行它。 – Evk
@Evk:感谢您的快速回复。我没有发布的代码是嵌套类,而且它们在这里真的不相关。如果您只是将错误消息添加到验证事件处理程序内的字符串列表中,则它应该足以进行测试。我的代码只是收集错误消息并从中创建另一个XML文档。就这样。 –