如何使用 XSD 验证使属性在 XML 中唯一
How to make an attribute unique in XML using XSD validation
我有这个 XML,name
属性值应该是唯一的,例如 A
、B
等:
<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: The content of preDefinedRecipeType
is invalid. Element unique
is invalid, misplaced, or occurs too often.
我觉得我做错了什么,但我是新手XSD,没看到。
我认为您需要将 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
放错地方了。参见 Where to place xs:unique constraint in 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>
我有这个 XML,name
属性值应该是唯一的,例如 A
、B
等:
<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: The content of
preDefinedRecipeType
is invalid. Elementunique
is invalid, misplaced, or occurs too often.
我觉得我做错了什么,但我是新手XSD,没看到。
我认为您需要将 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
放错地方了。参见 Where to place xs:unique constraint in 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>