我有兴趣定义XSD中的关键约束。 我的理解是使用 xs:key 应将用于参考值列表成员的值限制。

假设我们正在使用示例XSD,

<xs:schema
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        targetNamespace="namespace1"
        xmlns:r="namespace1"
        elementFormDefault="qualified">

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>

        <xs:element name="A" type="r:A" maxOccurs="unbounded">
          <xs:keyref name="dummy" refer="r:pNumKey">
            <xs:selector xpath="part"/>
            <xs:field xpath="@ref-number"/>
          </xs:keyref>
        </xs:element>

        <xs:element name="B" type="r:B"/>

      </xs:sequence>
    </xs:complexType>

    <xs:key name="pNumKey">
      <xs:selector xpath="r:B/r:part"/>
      <xs:field xpath="@key-number"/>
    </xs:key>

  </xs:element>

  <xs:complexType name="A">
    <xs:sequence>
      <xs:element name="part" maxOccurs="unbounded">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute name="ref-number" type="xs:integer"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="B">
    <xs:sequence>
      <xs:element name="part" maxOccurs="unbounded">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute name="key-number" type="xs:integer"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

</xs:schema>

样品XML,

<root xmlns="namespace1">
  <A>
    <!-- 
      if the ref-number is not equal to one of the key-number, 
      the validation will give error 
    -->
    <part ref-number="1"/>
  </A>
  <A>
    <!-- 
      if the ref-number is not equal to one of the key-number, 
      the validation will give error 
    -->
    <part ref-number="2"/>
  </A>
  <B>
    <part key-number="1"/>
    <part key-number="2"/>
    <part key-number="3"/>
  </B>
</root>

而且,一些简单的验证

[TestMethod]
public void Test_Schema()
{
    string schemaFileName = @"sampleSchema.xsd";
    string xmlFileName = @"sampleXml.xml";
    XmlReaderSettings settings = new XmlReaderSettings
    {
        ValidationType = ValidationType.Schema,
        ValidationFlags = 
            XmlSchemaValidationFlags.ProcessInlineSchema |
            XmlSchemaValidationFlags.ProcessSchemaLocation | 
            XmlSchemaValidationFlags.ReportValidationWarnings,
    };
    settings.Schemas.Add (schema);
    settings.ValidationEventHandler += 
        (o, e) => { throw new Exception("CRASH"); };

    XmlSchema schema = 
        XmlSchema.Read (
        File.OpenText (schemaFileName), 
        (o, e) => { throw new Exception ("BOOM"); });

    XmlReader reader = XmlReader.Create (xmlFileName, settings);
    while (reader.Read ()) { }
}

如何使用不良值 A/part[@ref-number]?

<root xmlns="namespace1">
  <A>
    <!-- doesn't go CRASH BOOM bang! why not? :( -->
    <part ref-number="5"/>
  </A>
  <B>
    <part key-number="1"/>
    <part key-number="2"/>
    <part key-number="3"/>
  </B>
</root>

上方是否有任何一个或全部XSD,XML或验证?还是我误解了预期的目的 xs:key?

有帮助吗?

解决方案

像往常 2个错误 在这个练习中。

  1. 第一个错误,验证身份约束是一个明确的过程,通过 XmlSchemaValidationFlags.ProcessIdentityConstraints 通过设置 XmlReaderSettings.ValidationFlag, , 和
  2. 第二个错误, MSDN样本 包含模式中的错误, <xs:selector xpath="part"/> 应该读 <xs:selector xpath="r:part"/>.

完整的工作样本如下,

<xs:schema
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        targetNamespace="namespace1"
        xmlns:r="namespace1"
        elementFormDefault="qualified">
  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="A" type="r:A" maxOccurs="unbounded">
          <xs:keyref name="dummy" refer="r:pNumKey">
            <!-- without 'r:' below, key was not recognized, boo-urns msdn! -->
            <xs:selector xpath="r:part"/>
            <xs:field xpath="@ref-number"/>
          </xs:keyref>
        </xs:element>
        <xs:element name="B" type="r:B"/>
      </xs:sequence>
    </xs:complexType>
    <xs:key name="pNumKey">
      <xs:selector xpath="r:B/r:part"/>
      <xs:field xpath="@key-number"/>
    </xs:key>
  </xs:element>

  <xs:complexType name="A">
    <xs:sequence>
      <xs:element name="part" maxOccurs="unbounded">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute name="ref-number" type="xs:integer"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="B">
    <xs:sequence>
      <xs:element name="part" maxOccurs="unbounded">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute name="key-number" type="xs:integer"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

XML样本

<root xmlns="namespace1">
  <A>
    <!-- goes CRASH BOOM bang! failure for the win! -->
    <part ref-number="5"/>
  </A>
  <B>
    <part key-number="1"/>
    <part key-number="2"/>
    <part key-number="3"/>
  </B>
</root>

简单验证器

[TestMethod]
public void Test_Schema()
{
    string schemaFileName = @"sampleSchema.xsd";
    string xmlFileName = @"sampleXml.xml";

    XmlSchema schema = 
        XmlSchema.Read(
        File.OpenText(schemaFileName), 
        (o, e) => { throw new Exception("BOOM"); });

    XmlReaderSettings settings = new XmlReaderSettings
    {
        ValidationType = ValidationType.Schema,
        ValidationFlags = 
            XmlSchemaValidationFlags.ProcessInlineSchema | 
            XmlSchemaValidationFlags.ProcessSchemaLocation | 
            XmlSchemaValidationFlags.ReportValidationWarnings | 

            // d'oh! explicit flag for processing identity constraints!
            XmlSchemaValidationFlags.ProcessIdentityConstraints,
    };
    settings.Schemas.Add(schema);
    settings.ValidationEventHandler += 
        (o, e) => { throw new Exception("CRASH"); };

    XmlReader reader = XmlReader.Create(xmlFileName, settings);
    while (reader.Read()) { }
}

其他提示

我想您应该使用验证eventhandler:

settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);

private static void ValidationCallBack (object sender, ValidationEventArgs args) {}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top