【解決方法】XML をスキーマに対して検証する際の問題 – 珍しいアプローチ

[ad_1]

こんにちは皆さん。

私はここに来たばかりなので、まだ私を殴らないでください。

質問を設定するために、これが私のシナリオです。 Winform にコントロールを動的に追加するアプリケーションを作成しています。 これは SQL データベースを介して行われます。 2 つのテキスト列を含むテーブルがあります。1 つは「質問」の列、もう 1 つは回答に必要な入力の種類 (TextBox、NumericUpDown、DataGridView など) の列、もう 1 つは「ControlSource」の列です。さまざまなものが含まれる可能性があります。

コントロールが DataGridView の場合、通常、「ControlSource」列には次のような XML スキーマが含まれます。

XML
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified">

<!-- U.S. State Abbreviations Type -->
<xsd:simpleType name="StateType">
   <xsd:restriction base="xsd:string">
      <xsd:enumeration value="AK"/>
      <xsd:enumeration value="AL"/>
      <xsd:enumeration value="AR"/>
      <xsd:enumeration value="AZ"/>
      <xsd:enumeration value="CA"/>
      <xsd:enumeration value="CO"/>
      <xsd:enumeration value="CT"/>
      <xsd:enumeration value="DC"/>
      <xsd:enumeration value="DE"/>
      <xsd:enumeration value="FL"/>
      <xsd:enumeration value="GA"/>
      <xsd:enumeration value="HI"/>
      <xsd:enumeration value="IA"/>
      <xsd:enumeration value="ID"/>
      <xsd:enumeration value="IL"/>
      <xsd:enumeration value="IN"/>
      <xsd:enumeration value="KS"/>
      <xsd:enumeration value="KY"/>
      <xsd:enumeration value="LA"/>
      <xsd:enumeration value="MA"/>
      <xsd:enumeration value="MD"/>
      <xsd:enumeration value="ME"/>
      <xsd:enumeration value="MI"/>
      <xsd:enumeration value="MN"/>
      <xsd:enumeration value="MO"/>
      <xsd:enumeration value="MS"/>
      <xsd:enumeration value="MT"/>
      <xsd:enumeration value="NC"/>
      <xsd:enumeration value="ND"/>
      <xsd:enumeration value="NE"/>
      <xsd:enumeration value="NH"/>
      <xsd:enumeration value="NJ"/>
      <xsd:enumeration value="NM"/>
      <xsd:enumeration value="NV"/>
      <xsd:enumeration value="NY"/>
      <xsd:enumeration value="OH"/>
      <xsd:enumeration value="OK"/>
      <xsd:enumeration value="OR"/>
      <xsd:enumeration value="PA"/>
      <xsd:enumeration value="RI"/>
      <xsd:enumeration value="SC"/>
      <xsd:enumeration value="SD"/>
      <xsd:enumeration value="TN"/>
      <xsd:enumeration value="TX"/>
      <xsd:enumeration value="UT"/>
      <xsd:enumeration value="VA"/>
      <xsd:enumeration value="VT"/>
      <xsd:enumeration value="WA"/>
      <xsd:enumeration value="WI"/>
      <xsd:enumeration value="WV"/>
      <xsd:enumeration value="WY"/>
   </xsd:restriction>
</xsd:simpleType>

<!-- definition of complex elements -->
<xsd:element name="DataItems">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="Name" type="xsd:string"/>
      <xsd:element name="Address" type="xsd:string"/>
      <xsd:element name="City" type="xsd:string"/>
      <xsd:element name="State" type="StateType"/>
      <xsd:element name="Zip" type="xsd:string"/>
      <xsd:element name="DOB" type="xsd:date"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>
</xsd:schema> 

ここで主な問題が発生します。DataGridview にバインドされている DataTable は基本データ型 (文字列、整数、浮動小数点、小数、ビットなど) のみを検証するため、XML スキーマを介して制限を設ける必要があります。ユーザーが入力できるもの。

たとえば、上記の XML スキーマを参照すると、データテーブル/グリッドに「State」列がある場合、ユーザーは「AK」、「AZ」、「CA」、「TX」などのみを入力できるはずですが、データテーブル「State」列に「ZZZ」と入力すると、検証されません (エラーがスローされます)。

DataTable から XML を読み取り、XmlDocument を作成し、それにスキーマを追加して、DataTable ではなくドキュメントを検証する必要があると考えています。 XML スキーマとユーザーが入力した XML データはどちらも文字列として利用できます (ファイル システムは使用されません)。 これが最善のアプローチだと思われますか? 私がこれまでに持っているものは次のとおりです。

VB
' **** BEGIN: Test Validation **** '
Dim objSettings As New System.Xml.XmlReaderSettings()
objSettings.CheckCharacters = True
objSettings.CloseInput = True
objSettings.ConformanceLevel = System.Xml.ConformanceLevel.Auto
objSettings.DtdProcessing = System.Xml.DtdProcessing.Ignore
objSettings.ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.ProcessInlineSchema Or System.Xml.Schema.XmlSchemaValidationFlags.ReportValidationWarnings Or System.Xml.Schema.XmlSchemaValidationFlags.AllowXmlAttributes Or System.Xml.Schema.XmlSchemaValidationFlags.ProcessIdentityConstraints
        objSettings.ValidationType = System.Xml.ValidationType.Schema

' Get a pointer to the grid's table datasource
Dim tblData As System.Data.DataTable = DirectCast(objCtrl.DataSource, System.Data.DataTable)

' Get a pointer to the table's DataSet
Dim rstData As System.Data.DataSet = tblData.DataSet

' Read the schema from the DataSet
Dim strXMLSchema As String = rstData.GetXmlSchema()

' Read the xml from the DataSet
Dim strXMLData As String = rstData.GetXml()

' Create an XmlReader object
Dim rdrXmlReader As System.Xml.XmlReader = System.Xml.XmlReader.Create(New System.IO.StringReader(strXMLSchema), objSettings)

' Create an XmlReader document object
Dim document As New System.Xml.XmlDocument()
document.LoadXml(strXMLData)

' Schema?  Not sure this is right... 
Dim schemas As New System.Xml.Schema.XmlSchemaSet()
schemas.Add("http://www.w3.org/2001/XMLSchema", System.Xml.XmlReader.Create(rdrXmlReader, objSettings))

Dim eventHandler As New System.Xml.Schema.ValidationEventHandler(AddressOf ValidationEventHandler)

document.Validate(eventHandler)
' **** END: Test Validation **** '

完全を期すために、(今のところ非常に単純な) ValidationEventHandler ルーチンを次に示します。

VB
Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal e As System.Xml.Schema.ValidationEventArgs)

   Select Case e.Severity
      Case System.Xml.Schema.XmlSeverityType.Error
         Console.WriteLine("Error: {0}", e.Message)
      Case System.Xml.Schema.XmlSeverityType.Warning
         Console.WriteLine("Warning {0}", e.Message)
   End Select
End Sub

コメントアウトされている「document.Validate(eventHandler)」の呼び出しで問題が発生します。列挙された「StateType」値の 1 つ以外のものを許可するため、スキーマに対して正しく検証されません。 そして、 validationEventHandler は確実に呼び出されていますが、何も起こりません。

助言がありますか?

前もって感謝します。

解決策 1

私が間違っていなければ… *.xsd ファイルは、検証が呼び出される前にロードされていません。

ここを見てください:
XmlSchemaSet を使用した XML スキーマ (XSD) 検証[^]
Extensions.Validate メソッド (XDocument、XmlSchemaSet、ValidationEventHandler)[^]

[ad_2]

コメント

タイトルとURLをコピーしました