none
XML Schema (C#) RRS feed

  • Вопрос

  • Приветствую.

    Вопрос про XML Schema и валидацию оной на C#. Суть такова: есть xml-файл. В нём из 4-х пространств имён мне необходимо будет проверять только значения, которые принадлежат одному пространству имён. Покажу для наглядности кусок этого xml-файла:

    	<Лист Формат="A4" ЧислоФорматов="4" Ширина="840.42" Высота="296.86">
    		<SSP:Стрелка id="3" svg-id="svg3" x="491.29" y="139.72" InvY="1" ТипУстройства="действующее" Ордината="125" Парк="0" Угол="180.00" ТипСтрПеревода="обыкновенный" ВидУправления="электрическая централизация" ТипОстряков="сплошные" ТипРельса="Р50" МаркаКрестовины="1/9" Спаренность="одиночная" СторПеревода="правая" Автовозврат="нет" ЭлОбогревПеревода="нет" Пневмоочистка="нет" НормальноеПоложение="без отклонения" ОрдСтолбика="0" ПоказСтолбик="нет" ПозСтолбикаX="-12.20" ПозСтолбикаY="-1.74" Угол2="32.00">
    			<bsl:etext id="4" editor:Имя="Наименование" x="-0.27" y="0.35" class="fnt1 fmt1">2</bsl:etext>
    			<bsl:etext id="5" visible="нет" editor:Имя="Ордината" x="0.00" y="0.00" class="fnt1 fmt2"></bsl:etext>
    			<bsl:etext id="6" editor:Имя="Ордината столбика" x="-12.20" y="-1.74" class="fnt1 fmt2">(0)</bsl:etext>
    			<bsl:etext editor:Имя="Пикет" x="-1.05" y="-52.61" angle="270.00" class="fnt1 fmt2"></bsl:etext>
    			<SSP:Привод Тип="2" Марка="СП-6М, МСТ-0,3;190в, пр" ВыходШибера="справа" ЭлОбогрев="нет"/>
    		</SSP:Стрелка>
    </Лист>

    Пространство имён называется SSP. Мне нужно проверять по xml schem'е правильность значения атрибутов элементов в SSP. Читал про xml schema и пока не смог разобраться, как её составить для моеё xml. Пользовался и генератором от MS и XMLSpy. Spy сгенерировал так (привожу кусок):

    			<xs:attribute name="ТипУстройства" use="required">
    				<xs:simpleType>
    					<xs:restriction base="xs:string">
    						<xs:enumeration value="действующее"/>
    					</xs:restriction>
    				</xs:simpleType>
    			</xs:attribute>

    А вопрос в следующем: Для ТипУстройства и для других атрибутов могут быть списки значений. Если я подправлю XML Schema, например, таким образом:

    			<xs:attribute name="ТипУстройства" use="required">
    				<xs:simpleType>
    					<xs:restriction base="xs:string">
    						<xs:enumeration value="действующее"/>
    <xs:enumeration value="значение2"/>
    <xs:enumeration value="значение3"/>
    <xs:enumeration value="значение4"/>
    					</xs:restriction>
    				</xs:simpleType>
    			</xs:attribute>

    Это будет корректно? Или как-то надо формировать xsd-файл другим образом? Спасибо за ответ.

    24 сентября 2012 г. 8:16

Ответы

  • Да, этот пример схемы корректный.
    • Помечено в качестве ответа Abolmasov Dmitry 26 сентября 2012 г. 7:31
    24 сентября 2012 г. 9:58
  • Спасибо. ВРоде как разобрался. По итогу в xsd-файле надо было задавать ограничения так:

          <xs:attribute name="ТипОстряков" form="unqualified">
    	  	<xs:simpleType>
    			<xs:restriction base="xs:string">
    			  <xs:enumeration value="сплошные"/>
    			  <xs:enumeration value="гибкие"/>
    			</xs:restriction>
    		</xs:simpleType>
    	  </xs:attribute>

    Обязательно указав при этом атрибут form, иначе валидатор будет говорить, что атрибут ТипОстряков не объявлен. Код C# я тоже немного подправил:

                foreach (Page page in doc.Pages)
                {
                    foreach (Element element in page.Elements)
                    {
                        if (element.NamespaceUri != sspNameSpace) continue;
                        validator.ValidateElement(element.XmlName, sspNameSpace, null);
                        
                        foreach (var attr in element.Attributes)
                        {
                            validator.ValidateAttribute(attr.Name, "", attr.Value, null);//schemaInfo);
                            //DisplaySchemaInfo();
                        }
                        validator.ValidateEndOfAttributes(null);
    
                    }
    
                    validator.ValidateEndElement(null);
                }

    Действительно, пространство имён для атрибута указывать не надо, т.к. атрибут принадлежит элементу, у которого указано пространство имён.


    • Помечено в качестве ответа Geokish 26 сентября 2012 г. 6:58
    26 сентября 2012 г. 6:58

Все ответы

  • Да, этот пример схемы корректный.
    • Помечено в качестве ответа Abolmasov Dmitry 26 сентября 2012 г. 7:31
    24 сентября 2012 г. 9:58
  • Хм. Всё равно как-то не так. Итак, всё сначала. Я сгенерировал xml schema с помощью утилиты xsd.exe от MS. Было создано три xsd файла. В коде я кажому namespace указал свой файл:

                XmlSchemaSet schemaSet = new XmlSchemaSet();
                string editorNameSpace = "http://www.domain.ru/OFTD/editor/v1.0";
                schemaSet.Add(editorNameSpace, "Стрелка_SSP.xsd");
                string ashapesNameSpace = "http://www.domain.ru/OFTD/libs/ashapes.AutoShapesLibrary/v1.0";
                schemaSet.Add(ashapesNameSpace, "Стрелка_SSP_app1.xsd");
                string sspNameSpace = "http://www.domain.ru/OFTD/SchematicStationPlan/v1.0";
                schemaSet.Add(sspNameSpace, "Стрелка_SSP_app2.xsd");

    Далее так:

                XmlNamespaceManager manager = new XmlNamespaceManager(reader.NameTable);
    
                // Assign a ValidationEventHandler to handle schema validation warnings and errors.
                
                XmlSchemaValidator validator = new XmlSchemaValidator(reader.NameTable, schemaSet, manager, XmlSchemaValidationFlags.None);
                validator.ValidationEventHandler += new ValidationEventHandler(SchemaValidationEventHandler);
    
                // Initialize the XmlSchemaValidator object.
                validator.Initialize();
    
                
                foreach (var page in doc.Pages)
                {
                    foreach (var element in page.Elements)
                    {
                        foreach (var attr in element.Attributes)
                        {
                            if (element.NamespaceUri != sspNameSpace) continue;
                            validator.ValidateElement(element.XmlName, sspNameSpace, null);
                            validator.ValidateAttribute(attr.Name, sspNameSpace, attr.Value, null);
                            validator.GetUnspecifiedDefaultAttributes(new ArrayList());
                            validator.ValidateEndOfAttributes(null);
                        }
                    }
                }
    И всё, вроде, красиво. Но вот какая штука. Если в исходном xml-файле я изменю значение атрибута на то, которого нет в xml schema, то валидатор ничего не скажет. Подскажите, пожалуйста.

    • Изменено Geokish 24 сентября 2012 г. 10:25
    24 сентября 2012 г. 10:21
  • Объясните, пожалуйста, по этому примеру: http://msdn.microsoft.com/ru-ru/library/ms162885%28v=vs.90%29.aspx

    Почему в строке проверка атрибута не указано пространство имен:

    validator.ValidateAttribute("genre", "", book.Genre, schemaInfo);

    Я взял в этом тестовом примере и наложил ограничения на жанр. В XML-файле умышленно изменил жанр. Затем вместо пустого пространства имён ввёл http://www.contoso.com/books, на что в консоли было получено сообщение:

    Атрибут "http://www.contoso.com/books:genre" не объявлен.
    Что это значит? Спасибо.
    25 сентября 2012 г. 10:01
  • Привет.

    Попробуйте использовать немного другой алгоритм проверки xml на соответсвие схеме, посмотрите этот пример.


    Для связи [mail]

    25 сентября 2012 г. 13:43
  • Привет.

    Скорей всего в данном случае проверяется атрибут в самом описании пространства xml. Атрибуты принадлежать к элементам xml и понятие namespace к ним наверное не очень применимо. В тоже время элементы xml уже объявлены в каком либо пространстве. Поэтому сначала выполняется проверка элемента с указанием пространтсва, а потом уже проверка атрибута у данного элемента.


    Для связи [mail]

    25 сентября 2012 г. 13:50
  • Спасибо. ВРоде как разобрался. По итогу в xsd-файле надо было задавать ограничения так:

          <xs:attribute name="ТипОстряков" form="unqualified">
    	  	<xs:simpleType>
    			<xs:restriction base="xs:string">
    			  <xs:enumeration value="сплошные"/>
    			  <xs:enumeration value="гибкие"/>
    			</xs:restriction>
    		</xs:simpleType>
    	  </xs:attribute>

    Обязательно указав при этом атрибут form, иначе валидатор будет говорить, что атрибут ТипОстряков не объявлен. Код C# я тоже немного подправил:

                foreach (Page page in doc.Pages)
                {
                    foreach (Element element in page.Elements)
                    {
                        if (element.NamespaceUri != sspNameSpace) continue;
                        validator.ValidateElement(element.XmlName, sspNameSpace, null);
                        
                        foreach (var attr in element.Attributes)
                        {
                            validator.ValidateAttribute(attr.Name, "", attr.Value, null);//schemaInfo);
                            //DisplaySchemaInfo();
                        }
                        validator.ValidateEndOfAttributes(null);
    
                    }
    
                    validator.ValidateEndElement(null);
                }

    Действительно, пространство имён для атрибута указывать не надо, т.к. атрибут принадлежит элементу, у которого указано пространство имён.


    • Помечено в качестве ответа Geokish 26 сентября 2012 г. 6:58
    26 сентября 2012 г. 6:58