Microsoft Corporation
June 10, 2004
Резюме
Dare Obasanjo на примерах показывает мало известные функциональные возможности классов в пространстве System.Xml.Schema.
Введение
Время от времени я вижу в конференциях и на форумах вопросы о том, как выполнить некоторую задачу по использованию схемы XML Schema, работа с которой, с одной стороны, предоставляется классами пространства имен System.Xml.Schema, но с другой стороны, неочевидно как выполнить поставленную задачу в этом пространстве имен.
Со временем я составил список задач, которые можно выполнить с классами в пространстве имен System.Xml.Schema, но которые не очевидны при первом использовании. Эта статья включает три первых пункта из этого списка.
Типичный пример: Книжный Инвентарь
Следующий пример схемы и XML документа использованы как вводные данные для этой статьи:
Books.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/books"
xmlns:bk="http://www.example.com/books"
attributeFormDefault="unqualified"
elementFormDefault="qualified">
<xs:element name="books">
<xs:complexType>
<xs:sequence>
<xs:element name="book" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string" />
<xs:element name="author" type="xs:string" />
</xs:sequence>
<xs:attribute name="publisher" type="bk:publisherType" use="required" />
<xs:attribute name="on-loan" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:annotation>
<xs:documentation xml:lang="en">
The publisherType is a list of the publishers I've bought books from.
If a publisher is not on the list then it means I don't have any books from them.
</xs:documentation>
</xs:annotation>
<xs:simpleType name="publisherType">
<xs:restriction base="xs:string">
<xs:enumeration value="WROX" />
<xs:enumeration value="Prentice Hall" />
<xs:enumeration value="Addison-Wesley" />
<xs:enumeration value="APress" />
<xs:enumeration value="IDG books" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
Books.xml
<books xmlns="http://www.example.com/books">
<book publisher="IDG books" on-loan="Sanjay">
<title>XML Bible</title>
<author>Elliotte Rusty Harold</author>
</book>
<book publisher="Addison-Wesley">
<title>The Mythical Man Month</title>
<author>Frederick Brooks</author>
</book>
<book publisher="WROX">
<title>Professional XSLT 2nd Edition</title>
<author>Michael Kay</author>
</book>
<book publisher="Prentice Hall" on-loan="Sander" >
<title>Definitive XML Schema</title>
<author>Priscilla Walmsley</author>
</book>
<book publisher="APress">
<title>A Programmer's Introduction to C#</title>
<author>Eric Gunnerson</author>
</book>
</books>
Подтверждение правильности значений простых переменных в приложении против определения простых типов в XSD
InfoPath позволяет создавать форму, основанную на XML Schema и привязать правила проверки к этой форме. Например, в форме, произведенной от books.xsd, поле publisher принимает в качестве верного только бы одно из значений: WROX, Prentice Hall, IDG books, Addison Wesley, APress. Я видел, что некоторые люди спрашивают, как выполнить подобную проверку в Windows Forms приложениях используя XML Schema в той же самой манере как InfoPath.
Ответ находится в методе ParseValue() класса System.Xml.Schema.XmlSchemaDatatype. Метод ParseValue() может использоваться, чтобы проверить, соответствует ли частное значение ограничениям заданного в XML Schema простого типа (simple type). Следующий отрывок кода показывает это в действии:
using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
namespace Test
{
class Program
{
static void Main(string[] args)
{
XmlSchema books =
XmlSchema.Read(new XmlTextReader("books.xsd"), null);
books.Compile(null);
XmlSchemaSimpleType pubType =
(XmlSchemaSimpleType) books.SchemaTypes[new
XmlQualifiedName("publisherType", "http://www.example.com/books")];
//works fine
Console.WriteLine(pubType.Datatype.ParseValue("WROX", new NameTable(), null));
//throws exception
//pubType.Datatype.ParseValue("Microsoft Press", new NameTable(), null);
}
}
}