Изменение XML-схем

Редактирование XML-схемы является одной из наиболее важных функций объектной модели схемы (SOM). Все свойства предварительной компиляции схемы SOM можно использовать для изменения существующих значений в схеме XML. Затем xml-схема может быть перекомпилирована, чтобы отразить изменения.

Первым шагом в редактировании схемы, загруженной в SOM, является обход схемы. Перед попыткой изменить схему следует ознакомиться с обходом схемы с помощью API SOM. Кроме того, необходимо ознакомиться со свойствами предварительной и после компиляции схемыCompilation-Infoset (PSCI).

Редактирование XML-схемы

В этом разделе приведены два примера кода, оба из которых редактируют схему клиента, созданную в разделе "Сборка XML-схем ". Первый пример кода добавляет новый PhoneNumber элемент к элементу Customer, а второй пример кода добавляет новый атрибут Title к элементу FirstName. Первый пример также использует коллекцию после компиляции XmlSchema.Elements схемы в качестве средства обхода схемы клиента, а второй пример кода использует коллекцию предварительной компиляции XmlSchema.Items схемы.

Пример элемента PhoneNumber

Этот первый пример кода добавляет новый PhoneNumber элемент в Customer элемент схемы клиента. Пример кода изменяет схему клиента в следующих шагах.

  1. Добавляет схему клиента в новый XmlSchemaSet объект, а затем компилирует его. Все предупреждения проверки схемы и ошибки, возникающие при чтении или компиляции схемы, обрабатываются делегатом ValidationEventHandler .

  2. Извлекает скомпилированный XmlSchema объект из XmlSchemaSet объекта, выполнив итерацию по свойству Schemas() . Поскольку схема скомпилирована, доступны свойства Post-Schema-Compilation-Infoset (PSCI).

  3. Создает элемент PhoneNumber с помощью класса XmlSchemaElement, использует ограничение простого типа xs:string с помощью классов XmlSchemaSimpleType и XmlSchemaSimpleTypeRestriction, добавляет аспект шаблона к свойству Facets ограничения, и добавляет ограничение к свойству Content простого типа, а простой тип — к свойству SchemaType элемента PhoneNumber.

  4. Выполняет итерацию по каждому элементу XmlSchemaElement в коллекции Values, относящейся к посткомпиляции схемы XmlSchema.Elements.

  5. Если значение элемента QualifiedName равно "Customer", определяет сложный тип элемента Customer с помощью класса XmlSchemaComplexType и частицу последовательности сложного типа с помощью класса XmlSchemaSequence.

  6. Добавляет новый PhoneNumber элемент в последовательность, содержащую существующие FirstName и LastName элементы, используя коллекцию предварительной компиляции Items схемы последовательности.

  7. Наконец, повторно обрабатывает и компилирует измененный XmlSchema объект с помощью Reprocess методов CompileXmlSchemaSet класса и записывает его в консоль.

Ниже приведен полный пример кода.

using System;
using System.Xml;
using System.Xml.Schema;

class XmlSchemaEditExample
{
    static void Main(string[] args)
    {
        // Add the customer schema to a new XmlSchemaSet and compile it.
        // Any schema validation warnings and errors encountered reading or
        // compiling the schema are handled by the ValidationEventHandler delegate.
        XmlSchemaSet schemaSet = new XmlSchemaSet();
        schemaSet.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
        schemaSet.Add("http://www.tempuri.org", "customer.xsd");
        schemaSet.Compile();

        // Retrieve the compiled XmlSchema object from the XmlSchemaSet
        // by iterating over the Schemas property.
        XmlSchema customerSchema = null;
        foreach (XmlSchema schema in schemaSet.Schemas())
        {
            customerSchema = schema;
        }

        // Create the PhoneNumber element.
        XmlSchemaElement phoneElement = new XmlSchemaElement();
        phoneElement.Name = "PhoneNumber";

        // Create the xs:string simple type restriction.
        XmlSchemaSimpleType phoneType = new XmlSchemaSimpleType();
        XmlSchemaSimpleTypeRestriction restriction =
            new XmlSchemaSimpleTypeRestriction();
        restriction.BaseTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

        // Add a pattern facet to the restriction.
        XmlSchemaPatternFacet phonePattern = new XmlSchemaPatternFacet();
        phonePattern.Value = "\\d{3}-\\d{3}-\\d(4)";
        restriction.Facets.Add(phonePattern);

        // Add the restriction to the Content property of the simple type
        // and the simple type to the SchemaType of the PhoneNumber element.
        phoneType.Content = restriction;
        phoneElement.SchemaType = phoneType;

        // Iterate over each XmlSchemaElement in the Values collection
        // of the Elements property.
        foreach (XmlSchemaElement element in customerSchema.Elements.Values)
        {
            // If the qualified name of the element is "Customer",
            // get the complex type of the Customer element
            // and the sequence particle of the complex type.
            if (element.QualifiedName.Name.Equals("Customer"))
            {
                XmlSchemaComplexType customerType =
                    element.ElementSchemaType as XmlSchemaComplexType;
                XmlSchemaSequence sequence =
                    customerType.Particle as XmlSchemaSequence;

                // Add the new PhoneNumber element to the sequence.
                sequence.Items.Add(phoneElement);
            }
        }

        // Reprocess and compile the modified XmlSchema object and write it to the console.
        schemaSet.Reprocess(customerSchema);
        schemaSet.Compile();
        customerSchema.Write(Console.Out);
    }

    static void ValidationCallback(object sender, ValidationEventArgs args)
    {
        if (args.Severity == XmlSeverityType.Warning)
            Console.Write("WARNING: ");
        else if (args.Severity == XmlSeverityType.Error)
            Console.Write("ERROR: ");

        Console.WriteLine(args.Message);
    }
}
Imports System.Xml
Imports System.Xml.Schema

Class XmlSchemaEditExample

    Shared Sub Main()

        ' Add the customer schema to a new XmlSchemaSet and compile it.
        ' Any schema validation warnings and errors encountered reading or 
        ' compiling the schema are handled by the ValidationEventHandler delegate.
        Dim schemaSet As XmlSchemaSet = New XmlSchemaSet()
        AddHandler schemaSet.ValidationEventHandler, AddressOf ValidationCallback
        schemaSet.Add("http://www.tempuri.org", "customer.xsd")
        schemaSet.Compile()

        ' Retrieve the compiled XmlSchema object from the XmlSchemaSet
        ' by iterating over the Schemas property.
        Dim customerSchema As XmlSchema = Nothing
        For Each schema As XmlSchema In schemaSet.Schemas()
            customerSchema = schema
        Next

        ' Create the PhoneNumber element.
        Dim phoneElement As XmlSchemaElement = New XmlSchemaElement()
        phoneElement.Name = "PhoneNumber"

        ' Create the xs:string simple type restriction.
        Dim phoneType As XmlSchemaSimpleType = New XmlSchemaSimpleType()
        Dim restriction As XmlSchemaSimpleTypeRestriction = _
            New XmlSchemaSimpleTypeRestriction()
        restriction.BaseTypeName = New XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")

        ' Add a pattern facet to the restriction.
        Dim phonePattern As XmlSchemaPatternFacet = New XmlSchemaPatternFacet()
        phonePattern.Value = "\\d{3}-\\d{3}-\\d(4)"
        restriction.Facets.Add(phonePattern)

        ' Add the restriction to the Content property of the simple type
        ' and the simple type to the SchemaType of the PhoneNumber element.
        phoneType.Content = restriction
        phoneElement.SchemaType = phoneType

        ' Iterate over each XmlSchemaElement in the Values collection
        ' of the Elements property.
        For Each element As XmlSchemaElement In customerSchema.Elements.Values

            ' If the qualified name of the element is "Customer", 
            ' get the complex type of the Customer element  
            ' and the sequence particle of the complex type.
            If element.QualifiedName.Name.Equals("Customer") Then

                Dim customerType As XmlSchemaComplexType = _
                    CType(element.ElementSchemaType, XmlSchemaComplexType)
                Dim sequence As XmlSchemaSequence = _
                    CType(customerType.Particle, XmlSchemaSequence)

                ' Add the new PhoneNumber element to the sequence.
                sequence.Items.Add(phoneElement)
            End If
        Next

        ' Reprocess and compile the modified XmlSchema object and write it to the console.
        schemaSet.Reprocess(customerSchema)
        schemaSet.Compile()
        customerSchema.Write(Console.Out)
    End Sub

    Shared Sub ValidationCallback(ByVal sender As Object, ByVal args As ValidationEventArgs)
        If args.Severity = XmlSeverityType.Warning Then
            Console.Write("WARNING: ")
        Else
            If args.Severity = XmlSeverityType.Error Then
                Console.Write("ERROR: ")
            End If
        End If
        Console.WriteLine(args.Message)
    End Sub

End Class

Ниже приведена измененная схема клиента, созданная в разделе "Сборка XML-схем ".

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://www.tempuri.org" targetNamespace="http://www.tempuri.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Customer">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="FirstName" type="xs:string" />
        <xs:element name="LastName" type="tns:LastNameType" />
        <xs:element name="PhoneNumber">           <xs:simpleType>             <xs:restriction base="xs:string">               <xs:pattern value="\d{3}-\d{3}-\d(4)" />             </xs:restriction>           </xs:simpleType>         </xs:element>
      </xs:sequence>
      <xs:attribute name="CustomerId" type="xs:positiveInteger" use="required" />
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="LastNameType">
    <xs:restriction base="xs:string">
      <xs:maxLength value="20" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

Пример атрибута title

Второй пример кода добавляет новый Title атрибут в FirstName элемент схемы клиента. В первом примере кода тип элемента FirstNamexs:string. Чтобы элемент FirstName имел атрибут и строковое содержимое, его тип должен быть изменен на сложный тип с моделью расширения простого содержимого.

Пример кода изменяет схему клиента в следующих шагах.

  1. Добавляет схему клиента в новый XmlSchemaSet объект, а затем компилирует его. Все предупреждения проверки схемы и ошибки, возникающие при чтении или компиляции схемы, обрабатываются делегатом ValidationEventHandler .

  2. Извлекает скомпилированный XmlSchema объект из XmlSchemaSet объекта, выполнив итерацию по свойству Schemas() . Поскольку схема скомпилирована, доступны свойства Post-Schema-Compilation-Infoset (PSCI).

  3. Создает новый сложный тип для FirstName элемента с помощью XmlSchemaComplexType класса.

  4. Создает новое простое расширение содержимого xs:string, с базовым типом, с использованием классов XmlSchemaSimpleContent и XmlSchemaSimpleContentExtension.

  5. Создает новый атрибут Title с помощью класса XmlSchemaAttribute, имеющего SchemaTypeName для xs:string, и добавляет атрибут в простое расширение содержимого.

  6. Устанавливает модель содержимого простого содержимого на расширение простого содержимого и модель содержимого сложного типа на простое содержимое.

  7. Добавляет новый сложный тип в коллекцию XmlSchema.Items предварительной компиляции схемы.

  8. Выполняет итерацию по каждому элементу XmlSchemaObject в коллекции схемы предварительной компиляции XmlSchema.Items.

Замечание

FirstName Так как элемент не является глобальным элементом схемы, он недоступен в XmlSchema.Items коллекциях или XmlSchema.Elements коллекциях. Пример кода находит элемент FirstName, сначала обнаружив элемент Customer.

Первый пример кода обходил схему с помощью коллекции, сформированной после компиляции схемы XmlSchema.Elements. В этом примере для обхода схемы используется коллекция предварительной компиляции XmlSchema.Items схемы. Хотя обе коллекции предоставляют доступ к глобальным элементам в схеме, итерация по коллекции Items является более трудоемкой, так как необходимо выполнить итерацию по всем глобальным элементам в схеме, и у неё нет никаких свойств PSCI. Коллекции PSCI (XmlSchema.Elements, и XmlSchema.AttributesXmlSchema.SchemaTypesт. д.) предоставляют прямой доступ к своим глобальным элементам, атрибутам и типам и их свойствам PSCI.

  1. Если XmlSchemaObject является элементом, QualifiedName которого равен "Customer", получите сложный тип элемента Customer с помощью класса XmlSchemaComplexType и частицу последовательности сложного типа с помощью класса XmlSchemaSequence.

  2. Выполняет итерацию по каждому элементу XmlSchemaParticle в коллекции схемы предварительной компиляции XmlSchemaSequence.Items.

  3. Если XmlSchemaParticle является элементом, чей QualifiedName равен "FirstName", устанавливает SchemaTypeName элемента FirstName в новый сложный тип FirstName.

  4. Наконец, повторно обрабатывает и компилирует измененный XmlSchema объект с помощью Reprocess методов CompileXmlSchemaSet класса и записывает его в консоль.

Ниже приведен полный пример кода.

using System;
using System.Xml;
using System.Xml.Schema;

class XmlSchemaEditExample
{
    static void Main(string[] args)
    {
        // Add the customer schema to a new XmlSchemaSet and compile it.
        // Any schema validation warnings and errors encountered reading or
        // compiling the schema are handled by the ValidationEventHandler delegate.
        XmlSchemaSet schemaSet = new XmlSchemaSet();
        schemaSet.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
        schemaSet.Add("http://www.tempuri.org", "customer.xsd");
        schemaSet.Compile();

        // Retrieve the compiled XmlSchema object from the XmlSchemaSet
        // by iterating over the Schemas property.
        XmlSchema customerSchema = null;
        foreach (XmlSchema schema in schemaSet.Schemas())
        {
            customerSchema = schema;
        }

        // Create a complex type for the FirstName element.
        XmlSchemaComplexType complexType = new XmlSchemaComplexType();
        complexType.Name = "FirstNameComplexType";

        // Create a simple content extension with a base type of xs:string.
        XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
        XmlSchemaSimpleContentExtension simpleContentExtension =
            new XmlSchemaSimpleContentExtension();
        simpleContentExtension.BaseTypeName =
            new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

        // Create the new Title attribute with a SchemaTypeName of xs:string
        // and add it to the simple content extension.
        XmlSchemaAttribute attribute = new XmlSchemaAttribute();
        attribute.Name = "Title";
        attribute.SchemaTypeName =
            new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");
        simpleContentExtension.Attributes.Add(attribute);

        // Set the content model of the simple content to the simple content extension
        // and the content model of the complex type to the simple content.
        simpleContent.Content = simpleContentExtension;
        complexType.ContentModel = simpleContent;

        // Add the new complex type to the pre-schema-compilation Items collection.
        customerSchema.Items.Add(complexType);

        // Iterate over each XmlSchemaObject in the pre-schema-compilation
        // Items collection.
        foreach (XmlSchemaObject schemaObject in customerSchema.Items)
        {
            // If the XmlSchemaObject is an element, whose QualifiedName
            // is "Customer", get the complex type of the Customer element
            // and the sequence particle of the complex type.
            if (schemaObject is XmlSchemaElement)
            {
                XmlSchemaElement element = schemaObject as XmlSchemaElement;

                if (element.QualifiedName.Name.Equals("Customer"))
                {
                    XmlSchemaComplexType customerType =
                        element.ElementSchemaType as XmlSchemaComplexType;

                    XmlSchemaSequence sequence =
                        customerType.Particle as XmlSchemaSequence;

                    // Iterate over each XmlSchemaParticle in the pre-schema-compilation
                    // Items property.
                    foreach (XmlSchemaParticle particle in sequence.Items)
                    {
                        // If the XmlSchemaParticle is an element, who's QualifiedName
                        // is "FirstName", set the SchemaTypeName of the FirstName element
                        // to the new FirstName complex type.
                        if (particle is XmlSchemaElement)
                        {
                            XmlSchemaElement childElement =
                                particle as XmlSchemaElement;

                            if (childElement.Name.Equals("FirstName"))
                            {
                                childElement.SchemaTypeName =
                                    new XmlQualifiedName("FirstNameComplexType",
                                    "http://www.tempuri.org");
                            }
                        }
                    }
                }
            }
        }

        // Reprocess and compile the modified XmlSchema object and write it to the console.
        schemaSet.Reprocess(customerSchema);
        schemaSet.Compile();
        customerSchema.Write(Console.Out);
    }

    static void ValidationCallback(object sender, ValidationEventArgs args)
    {
        if (args.Severity == XmlSeverityType.Warning)
            Console.Write("WARNING: ");
        else if (args.Severity == XmlSeverityType.Error)
            Console.Write("ERROR: ");

        Console.WriteLine(args.Message);
    }
}
Imports System.Xml
Imports System.Xml.Schema

Class XmlSchemaEditExample

    Shared Sub Main()

        ' Add the customer schema to a new XmlSchemaSet and compile it.
        ' Any schema validation warnings and errors encountered reading or 
        ' compiling the schema are handled by the ValidationEventHandler delegate.
        Dim schemaSet As XmlSchemaSet = New XmlSchemaSet()
        AddHandler schemaSet.ValidationEventHandler, AddressOf ValidationCallback
        schemaSet.Add("http://www.tempuri.org", "customer.xsd")
        schemaSet.Compile()

        ' Retrieve the compiled XmlSchema object from the XmlSchemaSet
        ' by iterating over the Schemas property.
        Dim customerSchema As XmlSchema = Nothing
        For Each schema As XmlSchema In schemaSet.Schemas()
            customerSchema = schema
        Next

        ' Create a complex type for the FirstName element.
        Dim complexType As XmlSchemaComplexType = New XmlSchemaComplexType()
        complexType.Name = "FirstNameComplexType"

        ' Create a simple content extension with a base type of xs:string.
        Dim simpleContent As XmlSchemaSimpleContent = New XmlSchemaSimpleContent()
        Dim simpleContentExtension As XmlSchemaSimpleContentExtension = _
            New XmlSchemaSimpleContentExtension()
        simpleContentExtension.BaseTypeName = _
            New XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")

        ' Create the new Title attribute with a SchemaTypeName of xs:string
        ' and add it to the simple content extension.
        Dim attribute As XmlSchemaAttribute = New XmlSchemaAttribute()
        attribute.Name = "Title"
        attribute.SchemaTypeName = _
            New XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")
        simpleContentExtension.Attributes.Add(attribute)

        ' Set the content model of the simple content to the simple content extension
        ' and the content model of the complex type to the simple content.
        simpleContent.Content = simpleContentExtension
        complexType.ContentModel = simpleContent

        ' Add the new complex type to the pre-schema-compilation Items collection.
        customerSchema.Items.Add(complexType)

        ' Iterate over each XmlSchemaObject in the pre-schema-compilation
        ' Items collection.
        For Each schemaObject As XmlSchemaObject In customerSchema.Items

            ' If the XmlSchemaObject is an element, whose QualifiedName
            ' is "Customer", get the complex type of the Customer element
            ' and the sequence particle of the complex type.
            If schemaObject.GetType() Is GetType(XmlSchemaElement) Then

                Dim element As XmlSchemaElement = CType(schemaObject, XmlSchemaElement)

                If (element.QualifiedName.Name.Equals("Customer")) Then
                    Dim customerType As XmlSchemaComplexType = _
                        CType(element.ElementSchemaType, XmlSchemaComplexType)

                    Dim sequence As XmlSchemaSequence = _
                       CType(customerType.Particle, XmlSchemaSequence)

                    ' Iterate over each XmlSchemaParticle in the pre-schema-compilation
                    ' Items property.
                    For Each particle As XmlSchemaParticle In sequence.Items

                        ' If the XmlSchemaParticle is an element, who's QualifiedName
                        ' is "FirstName", set the SchemaTypeName of the FirstName element
                        ' to the new FirstName complex type.
                        If particle.GetType() Is GetType(XmlSchemaElement) Then
                            Dim childElement As XmlSchemaElement = _
                                CType(particle, XmlSchemaElement)

                            If childElement.Name.Equals("FirstName") Then
                                childElement.SchemaTypeName = _
                                   New XmlQualifiedName("FirstNameComplexType", _
                                  "http://www.tempuri.org")
                            End If
                        End If
                    Next
                End If
            End If
        Next

        ' Reprocess and compile the modified XmlSchema object and write it to the console.
        schemaSet.Reprocess(customerSchema)
        schemaSet.Compile()
        customerSchema.Write(Console.Out)
    End Sub

    Shared Sub ValidationCallback(ByVal sender As Object, ByVal args As ValidationEventArgs)
        If args.Severity = XmlSeverityType.Warning Then
            Console.Write("WARNING: ")
        Else
            If args.Severity = XmlSeverityType.Error Then
                Console.Write("ERROR: ")
            End If
        End If
        Console.WriteLine(args.Message)
    End Sub

End Class

Ниже приведена измененная схема клиента, созданная в разделе "Сборка XML-схем ".

<?xml version="1.0" encoding=" utf-8"?>
<xs:schema xmlns:tns="http://www.tempuri.org" targetNamespace="http://www.tempuri.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Customer">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="FirstName" type="tns:FirstNameComplexType" />
        <xs:element name="LastName" type="tns:LastNameType" />
      </xs:sequence>
      <xs:attribute name="CustomerId" type="xs:positiveInteger" use="required" />
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="LastNameType">
    <xs:restriction base="xs:string">
      <xs:maxLength value="20" />
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="FirstNameComplexType">     <xs:simpleContent>       <xs:extension base="xs:string">         <xs:attribute name="Title" type="xs:string" />       </xs:extension>     </xs:simpleContent>   </xs:complexType>
</xs:schema>

См. также