none
Валидация xml файлов RRS feed

  • Вопрос

  • Столкнулась с проблемой создания единой xml схемы для валидации xml файлов. Данные в xml файле могут быть разными, в зависимости от того какое значение выбрал пользователь при сохранении xml файла. И каждый раз при чтение файл должен проверятся на валидность. При написании единой xml схемы, это дело оказалось очень муторным и запутанным, так как имеется много классов и переменных, которые должны сохранятся в xml файл. При попытке валидации хотя бы одного файла выскакивает ошибка на следующий атрибут в xml файле : xsi:type="DerivativeClass". Этот атрибут ну никак не хочет проходить валидацию. И теперь вопросы:

    1. Можно ли создать единую xml схему для валидации множества xml файлов?
    2. И как произвести валидацию атрибута xsi:type="DerivativeClass"? По xml файлу создала вручную xml схему с указанием наследника:
      XML:
    <?xml version="1.0" encoding="utf-8"?>
    <Part xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Tube xsi:type="OvalTube">
        <Type>OvalTube</Type>
        <WallThickness>20</WallThickness>
        <Height>20</Height>
        <Width>50</Width>
      </Tube>
    </Part>

    XSD:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
               xmlns:xs="http://www.w3.org/2001/XMLSchema" 
               attributeFormDefault="unqualified" 
               elementFormDefault="qualified">
      <xsd:element name="Part">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="Tube" type="OvalTube">
              <xsd:complexType name="Tube" abstract="true">
                <xsd:sequence>
                  <xsd:element name="Type" type="xsd:string" />
                  <xsd:element name="WallThickness" type="xsd:double" />
                </xsd:sequence>
              </xsd:complexType>
             </xsd:element>
              <xsd:complexType name="OvalTube">
                <xsd:complexContent>
                  <xsd:extension base="Tube">
                    <xsd:sequence>
                      <xsd:element name="Height" type="xsd:double" />
                      <xsd:element name="Width" type="xsd:double" />
                    </xsd:sequence>
                  </xsd:extension>
                </xsd:complexContent>
              </xsd:complexType>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xs:schema>

    Но всё равно ошибка при валидации. Может быть кто нибудь сталкивался с такой проблемой?


    • Изменено nigina_1989 17 декабря 2012 г. 10:09
    17 декабря 2012 г. 10:07

Ответы

  • Вопрос решён, нужно было просто создать отдельный xsd:complexType для каждого наследника и указать в xsd:extention родителя. Вообщем моя схема выглядит сейчас так:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified"
      targetNamespace="http://tempuri.org"
      xmlns="http://tempuri.org"
      elementFormDefault="qualified"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      
      <xsd:complexType name="TubeType">
        <xsd:sequence>
          <xsd:element name="Type" type="xsd:string"/>
          <xsd:element name="WallThickness" type="xsd:double"/>
        </xsd:sequence>
      </xsd:complexType>
      
      <xsd:complexType name="OvalTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Height" type="xsd:double"/>
              <xsd:element name="Width" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="BentTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Radius" type="xsd:double"/>
              <xsd:element name="Diameter" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="RectangularTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Height" type="xsd:double"/>
              <xsd:element name="Width" type="xsd:double"/>
              <xsd:element name="Radius" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="RoundTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Diameter" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="IntersectionType">
        <xsd:sequence>
          <xsd:element name="Type" type="xsd:string"/>
          <xsd:element name="Position" type="xsd:string"/>
          <xsd:element name="Cut" type="xsd:string"/>
          <xsd:element name="Movement" type="xsd:string"/>
          <xsd:element name="Burning" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      
      <xsd:complexType name="PlaneIntersection">
        <xsd:complexContent>
          <xsd:extension base="IntersectionType">        
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="TubeIntersection">
        <xsd:complexContent>
          <xsd:extension base="IntersectionType">
            <xsd:sequence>
              <xsd:element name="Diameter" type="xsd:double"/>
            </xsd:sequence>        
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="PartType"> 
        <xsd:sequence> 
          <xsd:element name="Tube" type="TubeType"/>
          <xsd:element name="Intersection" type="IntersectionType" maxOccurs="unbounded"/>
        </xsd:sequence>
      </xsd:complexType>
      
      <xsd:element name="Part" type="PartType"/>
    </xs:schema>

    Уже при чтении xml файла, будут искаться соответствующие наследники и элементы в схеме. Может кому нибудь пригодится.



    • Помечено в качестве ответа nigina_1989 26 декабря 2012 г. 21:19
    • Изменено nigina_1989 26 декабря 2012 г. 21:32
    26 декабря 2012 г. 21:18

Все ответы

  • Хм.... кажется разобралась с атрибутом xsi:type="OvalTube"  надо было в начале схемы объявить namespace:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema id="XMLSchema1"
        targetNamespace="http://tempuri.org/PART.xsd"
        elementFormDefault="qualified"
        xmlns="http://tempuri.org/PART.xsd"
        xmlns:mstns="http://tempuri.org/PART.xsd"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    >
      <xsd:element name="Part">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="Tube">
              <xsd:complexType>
                <xsd:sequence>
                  <xsd:element name="Type" type="xsd:string" />
                  <xsd:element name="WallThickness" type="xsd:double" />
                  <xsd:element name="Radius" type="xsd:double"/>
                  <xsd:element name="Diameter" type="xsd:double"/>
                </xsd:sequence>
              </xsd:complexType>
            </xsd:element>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xs:schema>

    Без namespace ругается на этот атрибут а вот уже с ним ничего не происходит. А вот первый вопрос остаётся без ответа. Можно ли создать единую схему для валидации разных xml файлов с разными значениями?



    • Изменено nigina_1989 17 декабря 2012 г. 14:46
    17 декабря 2012 г. 14:33
  • Привет.

    На сколько разные xml? Схема у всех xml должна быть одна, но могут быть необязательные ноды. Если xml отличаются только значениями внутри каких-то элементов, то они должны проходить валидацию.


    Для связи [mail]

    20 декабря 2012 г. 10:15
  • XML файлы отличаются названиями элементов. Примеры:

    <?xml version="1.0" encoding="utf-8"?>
    <Tube xmlns="http://tempuri.org"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://tempuri.org PART.xsd"
          xsi:type="OvalTube">
        <Type>OvalTube</Type>
        <WallThickness>20</WallThickness>
        <Height>20</Height>
        <Width>20</Width>
    </Tube>


    <?xml version="1.0" encoding="utf-8"?>
    <Tube xmlns="http://tempuri.org"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://tempuri.org PART.xsd"
          xsi:type="BentTube">
        <Type>BentTube</Type>
        <WallThickness>50</WallThickness>
        <Radius>45</Radius>
        <Diameter>200</Diameter>
    </Tube>

    Но кроме этих элементов могут быть ещё другие элементы. Я совсем запуталась уже. Пока что создала схему только для одного файла

    Схема:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified"
      targetNamespace="http://tempuri.org"
      xmlns="http://tempuri.org"
      elementFormDefault="qualified"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xs:complexType name="TubeType">
        <xs:sequence>
          <xs:element name="Type" type="xs:string"/>
          <xs:element name="WallThickness" type="xs:double"/>
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="OvalTube">
        <xs:complexContent>
          <xs:extension base="TubeType">
            <xs:sequence>
              <xs:element name="Height" type="xs:double"/>
              <xs:element name="Width" type="xs:double"/>
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>    
      <xs:element name="Tube" type="TubeType"/>  
    </xs:schema>

    Сам файл:

    <?xml version="1.0" encoding="utf-8"?>
    <Tube xmlns="http://tempuri.org"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://tempuri.org PART.xsd"
          xsi:type="OvalTube">
        <Type>OvalTube</Type>
        <WallThickness>20</WallThickness>
        <Height>20</Height>
        <Width>20</Width>
    </Tube>

    Но такой xml файл не читается из за аттрибутов: 

    xmlns="http://tempuri.org"
    xsi:schemaLocation="http://tempuri.org PART.xsd"

    Может быть есть какие нибудь идеи?


    • Изменено nigina_1989 21 декабря 2012 г. 11:19
    21 декабря 2012 г. 10:55
  • Теперь xml файл читается вместе с атрибутами, и совпадает с xml  схемой, и показывает ошибки, в случае если что то в файле не правильно. А как на счёт единой схемы для множества файлов?

    • Изменено nigina_1989 21 декабря 2012 г. 14:45
    21 декабря 2012 г. 13:02
  • Вопрос решён, нужно было просто создать отдельный xsd:complexType для каждого наследника и указать в xsd:extention родителя. Вообщем моя схема выглядит сейчас так:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified"
      targetNamespace="http://tempuri.org"
      xmlns="http://tempuri.org"
      elementFormDefault="qualified"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      
      <xsd:complexType name="TubeType">
        <xsd:sequence>
          <xsd:element name="Type" type="xsd:string"/>
          <xsd:element name="WallThickness" type="xsd:double"/>
        </xsd:sequence>
      </xsd:complexType>
      
      <xsd:complexType name="OvalTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Height" type="xsd:double"/>
              <xsd:element name="Width" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="BentTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Radius" type="xsd:double"/>
              <xsd:element name="Diameter" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="RectangularTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Height" type="xsd:double"/>
              <xsd:element name="Width" type="xsd:double"/>
              <xsd:element name="Radius" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="RoundTube">
        <xsd:complexContent>
          <xsd:extension base="TubeType">
            <xsd:sequence>
              <xsd:element name="Diameter" type="xsd:double"/>
            </xsd:sequence>
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="IntersectionType">
        <xsd:sequence>
          <xsd:element name="Type" type="xsd:string"/>
          <xsd:element name="Position" type="xsd:string"/>
          <xsd:element name="Cut" type="xsd:string"/>
          <xsd:element name="Movement" type="xsd:string"/>
          <xsd:element name="Burning" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      
      <xsd:complexType name="PlaneIntersection">
        <xsd:complexContent>
          <xsd:extension base="IntersectionType">        
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="TubeIntersection">
        <xsd:complexContent>
          <xsd:extension base="IntersectionType">
            <xsd:sequence>
              <xsd:element name="Diameter" type="xsd:double"/>
            </xsd:sequence>        
          </xsd:extension>
        </xsd:complexContent>
      </xsd:complexType>
      
      <xsd:complexType name="PartType"> 
        <xsd:sequence> 
          <xsd:element name="Tube" type="TubeType"/>
          <xsd:element name="Intersection" type="IntersectionType" maxOccurs="unbounded"/>
        </xsd:sequence>
      </xsd:complexType>
      
      <xsd:element name="Part" type="PartType"/>
    </xs:schema>

    Уже при чтении xml файла, будут искаться соответствующие наследники и элементы в схеме. Может кому нибудь пригодится.



    • Помечено в качестве ответа nigina_1989 26 декабря 2012 г. 21:19
    • Изменено nigina_1989 26 декабря 2012 г. 21:32
    26 декабря 2012 г. 21:18
  • Спасибо, что поделились решением проблемы. Это поможет тем, кто столкнется с подобной проблемой.


    Для связи [mail]

    27 декабря 2012 г. 7:56