2

XML 文字列とスキーマをロードして関数に渡しました。スキーマに対して XML を正しく検証していますが、常に最初の無効な要素のスコープで検証を停止します。無効なデータ、続行、無効/欠落した属性、続行、ただし無効な要素、停止し、そのスコープ内でそれ以上検証されません。

スキーマは次のとおりです。

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="items">
          <xs:complexType>
            <xs:sequence maxOccurs="unbounded">
              <xs:element name="foo">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="bar" type="xs:integer" />
                    <xs:element name="bat" type="xs:integer" />
                  </xs:sequence>
                  <xs:attribute name="attr1" type="xs:integer" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Xml は次のとおりです。

<root>
  <items>
    <foo attr1='1'>
      <invalid0>1</invalid0>
      <invalid1>b</invalid1>
    </foo>
    <foo attr1='1'>
      <invalid2>b</invalid2>
      <bat>b</bat>
    </foo>
    <foo attr1='1'>
      <bar>3</bar>
    </foo>
    <invalidFoo attr1='1'>
      <bar>d</bar>
      <bat>2</bat>
    </invalidFoo>
    <foo>
      <bar>3</bar>
      <bat>q</bat>
    </foo>
  </items>
</root>

したがって、この例で何が起こるかというと、バリデーターは最初に到達して<foo>確認し、それ以上<invalid0>検証しないため、 . Validator は次の.<foo><invalid1><foo>

次に<foo>、そこに<invalid2>属さない があり、<bat>要素の無効なデータ (整数ではなく文字列) をキャッチしようとしないことがわかります。そのまま次に進みます<foo>

次の要素に移動し<foo>、欠落に関するエラーをスローして、次の要素に移動します。クールです。<bat><foo>

当然のことながら、内部では<invalidFoo>検証を行いません。<invalidFoo>なぜなら、もちろん、<invalidFoo>?

私にとっての難点は、この時点でバリデーターが後続のすべての<foo>兄弟要素の検証を停止するため、最後の無効なデータが<bat>キャッチされないことです。だから今、私が尋ねている理由は、私が検証を使用している方法は、すべてのエラーを (または少なくともできるだけ多く) キャッチしてユーザーに戻そうとするからです。実際のコードで最初に行ったテストは、次のようなものでした。

<root>
  <items>
    <invalidFoo attr1='1'>
      <invalid0>1</invalid0>
      <invalid1>b</invalid1>
    </invalidFoo>
    <foo attr1='1'>
      <invalid2>b</invalid2>
      <bat>b</bat>
    </foo>
    <foo attr1='1'>
      <bar>3</bar>
    </foo>
    <invalidFoo attr1='1'>
      <bar>d</bar>
      <bat>2</bat>
    </invalidFoo>
    <foo>
      <bar>3</bar>
      <bat>q</bat>
    </foo>
  </items>
</root>

そのため、バリデーターは最初<invalidFoo>にそれを見て停止しました。長い間、何らかの理由で検証が常に最初のエラーで停止していると想定していました。有効な<foo>バックを追加するまで、他の無効なデータエラーを連続してキャッチして蓄積し始めました。しかし、無効な要素タグ名にヒットするとすぐに、すべての兄弟/子レベルの検証がスキップされます。属性やデータではなく、無効な要素でのみ発生します。

今、私はこれが正しいか間違っていると言っているのではありません.これが正しいか間違っているかを尋ねています. 特に兄弟要素の場合、バリデーターは続行する必要がありますか? それとも、前の要素が無効であることに基づいて、基本的に要素のリスト全体を無効にする必要がありますか? この状況で Xml Schema Validator に期待される動作は何ですか?

これはすべて、次の C# コードを使用して行われています (期待どおりに動作します)。

 public static void ValidateAgainstSchema(string XMLSourceDocument, XmlSchemaSet validatingSchemas)
 {
    if (validatingSchemas == null)
    {
        throw new ArgumentNullException("In ValidateAgainstSchema: No schema loaded.");
    }

    string errorHolder = string.Empty;
    ValidationHandler handler = new ValidationHandler();

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.CloseInput = true;
    settings.ValidationType = ValidationType.Schema;
    settings.ValidationEventHandler += new ValidationEventHandler(handler.HandleValidationError);
    settings.Schemas.Add(validatingSchemas);
    settings.ValidationFlags =
        XmlSchemaValidationFlags.ReportValidationWarnings |
        XmlSchemaValidationFlags.ProcessIdentityConstraints |
        XmlSchemaValidationFlags.ProcessInlineSchema |
        XmlSchemaValidationFlags.ProcessSchemaLocation;

    StringReader srStringReader = new StringReader(XMLSourceDocument);

    using (XmlReader validatingReader = XmlReader.Create(srStringReader, settings))
    {
        while (validatingReader.Read()) { }
    }

    if (handler.MyValidationErrors.Count > 0)
    {
        foreach (String messageItem in handler.MyValidationErrors)
        {
            errorHolder += messageItem;
        }
        throw new XmlSchemaValidationException(errorHolder);
    }
}

検証イベント ハンドラーはエラーをキャッチし、IList<string>後でまとめて表示するためにそれらを に追加します。

4

1 に答える 1

2

木を歩くことで要素を処理するため、収まらないノードを取得するとすぐに失われます。ただし、属性は階層的ではなく、リストであるため、ストレートゴー/ノーゴーであり、続行できます。タイプチェックも簡単です。

あなたはあなたの例を見て、それがこれについてはどうであるかをうまく扱うことができると考えることができます。

<root>
  <items>
    <invalidFoo attr1='1'>
      <invalid0>1</invalid0>
      <invalid1>b</invalid1>
      <foo attr1='1'>
        <bar>b</bar>
        <bat>b</bat>
      </foo>    
    </invalidFoo>
  <items>
<root>

fooはアイテムの子として扱われるべきかどうか。fooは本当にfooですか?

実際のヘッドベンダーが必要な場合はxsd:choice、そこに1つまたは2つあり、スキーマに適合しない有効なノードを選択することを想像してください。これは、試して続行するのが「危険」な状況の1つです。そのため、最初にこれを修正する必要があると言われ、その後に何が起こるかを賢明に検証できるようになります。

于 2012-11-09T22:31:46.363 に答える