Как сделать атрибут уникальным в XML, используя проверку XSD - PullRequest
1 голос
/ 20 января 2020

У меня есть XML, и значения атрибута name должны быть уникальными, как A, B, et c:

<preDefinedRecipes>

       <preDefinedRecipe type="BREAD" name="A" ordinal="1" writerLevel="Service">

           <description>           <!-- // optional-->
           </description>

           <parameterDef ref="SUGAR_QTY" value="3" />
               <parameterDef ref="SALT_QTY" value="3" />
               <parameterDef ref="OIL_QTY" value="1" /> 

       </preDefinedRecipe>
       <preDefinedRecipe type="BREAD" name="B" ordinal="2" writerLevel="Service">

           <description>           <!-- // optional-->
           </description>

           <parameterDef ref="SUGAR_QTY" value="5" />
               <parameterDef ref="SALT_QTY" value="7" />
               <parameterDef ref="FLOUR_QTY" value="3" />

       </preDefinedRecipe>
   </preDefinedRecipes>

Это мой XSD-файл:

<xs:complexType name="preDefinedRecipeType">
    <xs:sequence>
      <xs:element type="xs:string" name="description">
      </xs:element>

    <xs:element type="preDefinedRecipeParameterDefType" name="parameterDef" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="type" use="required"/>
    <xs:attribute type="xs:string" name="name" use="required"/>
    <xs:attribute type="xs:byte" name="fieldbusId" use="optional"/>
    <xs:attribute type="xs:byte" name="ordinal" use="required"/>
    <xs:attribute type="xs:string" name="writerLevel" use="required"/>

     <xs:unique name="uniqueTitle">
      <xs:selector xpath="recipeConfig/preDefinedRecipes/preDefinedRecipe"/>
      <xs:field xpath="@name"/>
      </xs:unique>
  </xs:complexType>


  <xs:complexType name="preDefinedRecipesType">
    <xs:sequence>
      <xs:element type="preDefinedRecipeType" name="preDefinedRecipe" maxOccurs="unbounded" minOccurs="0">
        <xs:annotation>
          <xs:documentation>Default recipe names shall be translatable, user defined recipes shall never be 
             translated to avoid collisions.</xs:documentation>
        </xs:annotation>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

Я добавил xs:unique элемент для поля и селектора, но он выдает следующую ошибку:

SAX Exception: s4s-elt-invalid-content.1: содержимое preDefinedRecipeType недействительно. Элемент unique недопустим, смещен или встречается слишком часто.

Я думаю, что делаю что-то не так, но я новичок в XSD и не вижу его.

Ответы [ 2 ]

1 голос
/ 20 января 2020

Ваш xs:unique неуместен. См. Где разместить xs: ограничение уникальности в XSD?

Применительно к вашему случаю следующий XSD потребует, чтобы preDefinedRecipe/@name был уникальным с preDefinedRecipes:

XSD

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           elementFormDefault="qualified">
  <xs:complexType name="preDefinedRecipeType">
    <xs:sequence>
      <xs:element type="xs:string" name="description"/>   
      <xs:element type="preDefinedRecipeParameterDefType" name="parameterDef"
                  maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="type" use="required"/>
    <xs:attribute type="xs:string" name="name" use="required"/>
    <xs:attribute type="xs:byte" name="fieldbusId" use="optional"/>
    <xs:attribute type="xs:byte" name="ordinal" use="required"/>
    <xs:attribute type="xs:string" name="writerLevel" use="required"/>
  </xs:complexType>
  <xs:complexType name="preDefinedRecipeParameterDefType">
    <xs:attribute type="xs:string" name="ref" use="required"/>
    <xs:attribute type="xs:string" name="value" use="required"/>
  </xs:complexType>
  <xs:complexType name="preDefinedRecipesType">
    <xs:sequence>
      <xs:element type="preDefinedRecipeType" name="preDefinedRecipe" 
                  maxOccurs="unbounded" minOccurs="0">
        <xs:annotation>
          <xs:documentation>Default recipe names shall be translatable, user defined 
              recipes shall never be translated to avoid collisions.</xs:documentation>
        </xs:annotation>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="preDefinedRecipes" type="preDefinedRecipesType">
    <xs:unique name="uniqueTitle">
      <xs:selector xpath="preDefinedRecipe"/>
      <xs:field xpath="@name"/>
    </xs:unique>
  </xs:element>
</xs:schema>

XML

<?xml version="1.0" encoding="UTF-8"?>
<preDefinedRecipes>
  <preDefinedRecipe type="BREAD" name="A" ordinal="1" writerLevel="Service">
    <description/>
    <parameterDef ref="SUGAR_QTY" value="3" />
    <parameterDef ref="SALT_QTY" value="3" />
    <parameterDef ref="OIL_QTY" value="1" /> 
  </preDefinedRecipe>
  <preDefinedRecipe type="BREAD" name="B" ordinal="2" writerLevel="Service">
    <description/>
    <parameterDef ref="SUGAR_QTY" value="5" />
    <parameterDef ref="SALT_QTY" value="7" />
    <parameterDef ref="FLOUR_QTY" value="3" />
  </preDefinedRecipe>
</preDefinedRecipes>
0 голосов
/ 20 января 2020

Я думаю, вам нужно объявить тип данных атрибута name как xs: ID вместо xs: string: https://www.w3.org/TR/xmlschema11-2/#ID

<xs:attribute type="xs:ID" name="name" use="required"/>

В соответствии с этим XSD 1.1 spe c, XSD 1.1. процессор будет обеспечивать ограничение уникальности (а процессор XSD 1.0, вероятно, не будет).

...