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:迅速な返信をありがとう。私が投稿しなかったコードはネストされたクラスであり、ここでは本当に無関係です。 validationeventhandler内の文字列のリストにエラーメッセージを追加するだけであれば、テストで十分です。私のコードでは、エラーメッセージを収集し、別のXMLドキュメントを作成しています。それで全部です。 –