Проверка схемы Xml с помощью xsd

Я пытаюсь проверить следующий Xml.

string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
                    <ROOT xmlns:bk=""urn:samples"">
                        <RandomName1>
                            <Element1>v</Element1>
                            <Element2>v</Element2>
                            <Element3>v</Element3>
                            <Element4>v</Element4>
                    </RandomName1>
                        <RandomName2>
                            <Element1>v</Element1>
                            <Element2>v</Element2>
                            <Element3>v</Element3>
                            <Element4>v</Element4>
                    </RandomName2>
                    </ROOT>";

RandomNameN — любая строка. Я заинтересован в том, чтобы Element1 - Element4 присутствовал и правильно назывался, а также чтобы схема соответствовала.

Я пробовал следующее

string xsdMarkup =
                @"<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
                   <xsd:element name='ROOT'>
                    <xsd:complexType>
                     <xsd:sequence>
                      <xsd:any>
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name ='Element1'/>
                                <xsd:element name ='Element2'/>
                                <xsd:element name ='Element3'/>
                                <xsd:element name ='Element4'/>
                            </xsd:sequence>
                        </xsd:complexType>
                        </xsd:any>
                     </xsd:sequence>
                    </xsd:complexType>
                   </xsd:element>
                  </xsd:schema>";

XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(new StringReader(xsdMarkup)));

var xDoc = XDocument.Parse(xml);

bool errors = false;
string msg = string.Empty;

xDoc.Validate(schemas, (o, e) =>
    {
        msg = e.Message;
        errors = true;
    });

Я получаю System.Xml.Schema.XmlSchemaException

Элемент 'http://www.w3.org/2001/XMLSchema:complexType' не поддерживается в этом контексте.

Мне также нужно знать, как сделать так, чтобы узлы RandomName1 не требовали имени, а присутствовали. Я пытался добиться этого через </xsd:any> вместо </xsd:element>


person Sam Leach    schedule 09.08.2013    source источник
comment
Вы не можете определить сложный тип внутри ‹xsd:any›. ‹xsd:any› относится к типу элементов в последовательности, а не только к их имени. Это позволяет последовательности, окружающей его, содержать элементы любого типа. Однако вы можете ограничить возможности, указав пространство имен. См.: msdn.microsoft.com/en-us/library/ms256043. .aspx   -  person W Almir    schedule 09.08.2013


Ответы (2)


Как я упоминал в моем комментарии, использование <xsd:any> неверно.

Кроме того, <xsd:sequence> также не может содержать комплексный тип. См.: http://msdn.microsoft.com/en-us/library/ms256089.aspx

Я бы также посоветовал не использовать такие шаблоны, как RandomNameN, для идентификации ваших элементов, а больше похоже на: <RandomName id='N'>. Говоря об объектно-ориентированном подходе, вы можете думать о своем XSD как о своем классе, где complexTypes — это классы, а elements — ссылки на экземпляры complexTypes классов, поэтому для элементов вы также должны определить их type.

Затем ваш XML-документ будет представлять ваши объекты. Где тип объекта представлен в теге.

Ваш сложный тип может быть обернут внутри элемента. И поскольку у вас есть переменное количество элементов в последовательности, вы должны установить maxOccurs на неограниченное. Ваша результирующая схема должна выглядеть так:

    <xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
       <xsd:element name='ROOT'>
          <xsd:complexType>
            <xsd:sequence>
               <xsd:element name="RandomName" maxOccurs='unbounded'>
                  <xsd:complexType>
                     <xsd:sequence>
                       <xsd:element name="Element" minOccurs='4' maxOccurs='4' type="xsd:string" />
                    </xsd:sequence>
                  </xsd:complexType>
               </xsd:element>
            </xsd:sequence>
          </xsd:complexType>
       </xsd:element>
    </xsd:schema>>

В этом случае ваш XML может выглядеть так:

<ROOT >
     <RandomName>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
     </RandomName>
     <RandomName>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
     </RandomName>
 </ROOT> 

Наконец, если RandomName1 - RandonNameN относятся к одному и тому же типу (или классу, если мы говорим об объектно-ориентированном подходе), то теги в XML-файле также должны быть одинаковыми. То же самое касается Элемент1-Элемент4.

Однако, если они относятся к разным типам, но имеют общие элементы, вы можете использовать наследование.

Element1 может выглядеть, например, так:

<complexType name="Element1">
    <complexContent>
        <extension base="Element">
            <sequence>
                <xs:element type="xs:string" name="additionalField"/>
            </sequence>
        </extension>
    </complexContent>
</complexType>
person W Almir    schedule 09.08.2013

Я не знаю, находится ли производитель xml под вашим контролем. Если это так, вы можете решить это, например. используя элемент с фиксированным именем с некоторым атрибутом, содержащим случайное имя, что-то вроде <FixedNameElement randomName="...">.

person Jirka Š.    schedule 09.08.2013