Секреты простраства имен System.Xml.Schema(перевод статьи)

Dare Obasanjo
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);

}
}
}