XS: المفتاح ، لماذا يتم تمرير التحقق من الصحة عندما لا تكون قيمة المفتاح عضوًا في المرجع الرئيسي؟
-
30-09-2019 - |
سؤال
أنا مهتم بتحديد قيود رئيسية في 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 أخطاء في هذا التمرين.
- الخطأ الأول ، التحقق من صحة قيود الهوية هو عملية واضحة ، مستحثة عبر
XmlSchemaValidationFlags.ProcessIdentityConstraints
التي وضعتهاXmlReaderSettings.ValidationFlag
, ، و - الخطأ الثاني ، عينة 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()) { }
}
نصائح أخرى
أعتقد أنه يجب عليك استخدام ValityEventHandler:
settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
private static void ValidationCallBack (object sender, ValidationEventArgs args) {}
لا تنتمي إلى StackOverflow