2011-12-15 6 views
2

次のコードを使用して、XSDファイルに対してXMLファイルを検証します。エラーが検出され、XMLファイル内のxmlnsの値が有効な場合、検証ハンドラが正常に呼び出されます。無効な場合、検証ハンドラは呼び出されません。XmlDocument.Validateが無効な名前空間をチェックしない

private void ui_validate_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     ui_output.Text = ""; 

     XmlDocument xml_document = new XmlDocument(); 
     xml_document.LoadXml(ui_XML.Text); 
     xml_document.Schemas.Add(null, XmlReader.Create(new System.IO.StringReader(ui_XSD.Text))); 
     xml_document.Validate(validation_handler); 
    } 
    catch (Exception ex) 
    { 
     ui_output.Text = "Exception: " + ex.Message; 
    } 
} 

private void validation_handler(object sender, ValidationEventArgs e) 
{ 
    switch (e.Severity) 
    { 
     case XmlSeverityType.Error: 
      ui_output.Text += "Error: " + e.Message + Environment.NewLine; 
      break; 
     case XmlSeverityType.Warning: 
      ui_output.Text += "Warning: " + e.Message + Environment.NewLine; 
      break; 
    } 
} 

更新 受け入れ答えのための例:

XmlDocument xml_document = new XmlDocument(); 
xml_document.Load(@"C:\temp\example.xml"); 
xml_document.Schemas.Add(null, @"C:\temp\example.xsd"); 
xml_document.Schemas.Compile(); 

XmlQualifiedName xml_qualified_name = new XmlQualifiedName(xml_document.DocumentElement.LocalName, xml_document.DocumentElement.NamespaceURI); 
bool valid_root = xml_document.Schemas.GlobalElements.Contains(xml_qualified_name); 

答えて

4

私がこれを処理する方法は、実際にはドキュメント要素(ルート要素)に対してXmlSchemaElementがXmlReaderSettings.Schemasであることを最初に確認することです。存在しない場合、検証を実行することはできません。そのため、エラーは発生しません。

だから、あなたのXmlSchemaSet is compiled; LocalNameNamespaceUriを使用してXmlQualifiedNameを作成します。 GlobalElementsを使用してXmlSchemaElementを参照するために使用します。

i)スキーマが正常にコンパイルされ、ii)実際にドキュメントのルート要素の定義がある場合にのみ、検証を試みる必要があります。

1

ドキュメントのルート要素の名前空間が、その後バリができない、あなたのスキーマのターゲット名前空間と一致しない場合ルート要素(または、おそらくいずれかの要素)の定義を持つスキーマを見つけます。これは、正しい構造体の知識がないため、バリデーターは無効な構造体を報告できないことを意味します。そのような場合、バリデータは一般的に検証をスキップしたり、緩やかな検証(スキーマ定義が見つかった要素のみ検証)を実行したり、スキーマ定義が見つからないという警告を出したりすることができます。

少なくとも2つの選択肢があると思います:1)ドキュメントから名前空間を読み取り、別のチェックを使用して正しいかどうかを確認するか、2)バリデータの動作を変更する可能性があるかどうかを確認します指定された名前空間の定義が見つからないことを通知するように設定します。

0

@PetruGardea ...それがお役に立てば幸い - あなたの答えのために大きな感謝を!

var doc = new XmlDocument(); 
var set = new XmlSchemaSet(); 

var xsdString = @"<xs:schema 
    xmlns=""http://www.sample.ru/system"" 
    targetNamespace=""http://www.sample.ru/system"" 
    xmlns:xs=""http://www.w3.org/2001/XMLSchema"" 
    elementFormDefault=""qualified""> 

    <xs:element name=""Test""> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name=""B"" > 
     </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 

</xs:schema>"; 

using (var memStream = new MemoryStream()) 
{ 
    var data = Encoding.Default.GetBytes(xsdString); 
    memStream.Write(data, 0, data.Length); 
    memStream.Position = 0; 
    using (var reader = XmlReader.Create(memStream)) 
    { 
     set.Add(@"http://www.sample.ru/system", reader); 
    } 
} 

//doc.LoadXml(@"<a1:Test xmlns:a1=""http://www.sample.ru/system""><a1:B /></a1:Test>"); // valid xml - no errors 
//doc.LoadXml(@"<a1:Test xmlns:a1=""http://www.sample.ru/system""><a1:B1 /></a1:Test>"); // invalid xml - error about B1 
doc.LoadXml(@"<a1:Test xmlns:a1=""http://www.sample.ru/system1""><a1:B1 /></a1:Test>"); // invalid xml with bad namespace - error about namespace 
//doc.LoadXml(@""); // no need to worry that doc.FirstChild is null - in this case this line throws exception 

doc.Schemas.Add(set); 

// !!!! you need to add this code to check for wrong namespace !!!! 
var baseUri = doc.FirstChild.NamespaceURI; 
if (!doc.Schemas.Contains(baseUri)) 
{ 
    Console.WriteLine("Error: there is not xsd to validate this document (uri = {0})", baseUri); 
} 

// the rest of the code just prints validation errors and warnings 
doc.Validate((sender, e) => 
{ 
    Console.WriteLine(e.Message); 
}); 
:他の人がそれをグーグルする必要はありませんので

私はちょうどあなたのソリューションを実証するために、ここでいくつかのコードを入れて

関連する問題