【问题标题】:How to make an attribute unique in XML using XSD validation如何使用 XSD 验证使属性在 XML 中唯一
【发布时间】:2020-01-20 10:31:53
【问题描述】:

我有这个 XML,name 属性值应该是唯一的,例如 AB 等:

<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 异常:s4s-elt-invalid-content.1:preDefinedRecipeType 的内容无效。元素unique 无效、放错位置或出现过于频繁。

我认为我做错了什么,但我是 XSD 的新手,看不到它。

【问题讨论】:

    标签: xml xsd xsd-validation xml-validation


    【解决方案1】:

    您的xs:unique 放错地方了。见Where to place xs:unique constraint in XSD?

    适用于您的情况,以下 XSD 将要求 preDefinedRecipe/@namepreDefinedRecipes 是唯一的:

    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>
    

    【讨论】:

      【解决方案2】:

      我认为你需要将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 规范,XSD 1.1。处理器将强制执行唯一性约束(XSD 1.0 处理器可能不会)。

      【讨论】:

      • xs:unique 可以完成这项工作,并且比 xs:ID 更灵活。此外,在 1.0 和 1.1 之间没有影响 xs:ID 的重大变化
      • xs:ID 仅适用于字符串,但是当我尝试使用数字时它不起作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多