在XSD中,如何显示元素只能在具有特定属性的父元素中?
In XSD, how do I show that an element can only be in a parent with a certain attribute?
我正在尝试记录其他人的手写代码 XML,我希望 XSD 能帮助我做到这一点。然而,我被无知所阻碍:我还不能保证 XSD 对整个事情都有效。 (请随时告诉我某些东西是糟糕的编码风格,但我只是文档编写者,而不是开发人员。)
反正我的情况是:
<items>
<item name="foo">
<coolThing>wah!</coolThing>
</item>
<item name="bar">
<needfulThing>address</needfulThing>
</item>
</items>
(当然是实际条款。)<coolThing>
元素只能出现在<item name="foo">
容器中,<needfulThing>
元素只能出现在[=16=中]容器。
如何在 XSD 中指定它?我正在查看的教程方便地忽略了这一点。
是否像将分类元素定义为属性声明的子元素一样简单:
<xs:attribute name="foo" type="xs:string">
<xs:element name="coolThing" type="xs:string"/>
</xs:attribute>
(为清楚起见,省略了一些内容。)当然,这不会让我轻易地指定 <coolThing>
可以同时出现在 <item name="foo">
和 <item name="baz">
元素中,如果出现这种情况。
还是我遗漏了什么? (很有可能。)
是的,您从根本上忽略了 XSD(以及其他 XML 模式)旨在将元素与基于 name[= 的类型相关联40=] 元素的属性,而不是元素的属性。
因此,使用 item
或 object
或 thing
等通过 name
等属性区分的过于通用的元素被视为反模式. XSD 1.1 有一个允许表达此类约束的断言机制,但实际上你会通过断言人为地重新实现自然包含约束——而不是你想要的地方。
具体来说,不是一般地设计 XML 元素,
<item name="foo"/>
让它们的元素名称传达它们的性质:
<foo/>
然后您会发现 XSD 1.0 中可用的普通内容模型足以表达您的包含限制。
更新:Michael Kay 让我想起了另一个 XSD 1.1 机制,它不如断言强大,但如果您只需要改变每个属性的类型,它更适合值:条件类型分配...
如果您坚持使用过于通用的元素名称并寻求在事后编写模式,在 XSD 1.1 的断言之前,请考虑 XSD 1.1 的 Conditional Type Assignment,它允许根据属性值分配类型。
可在此处找到完整的工作示例:
您可以使用 XSD 1.1 和 类型替代品 来执行此操作。参见示例 XSD 1.1 alternative usage issue。此功能明确设计用于执行您想要的操作 - 使元素的类型取决于属性的值,而不是元素的名称。
但是您需要 XSD 1.1 处理器。我知道三个:Altova、Saxon 和 Apache Xerces。许多广泛使用的 XSD 处理器,例如 Microsoft 的处理器,从未更新到 XSD 1.1。
我正在尝试记录其他人的手写代码 XML,我希望 XSD 能帮助我做到这一点。然而,我被无知所阻碍:我还不能保证 XSD 对整个事情都有效。 (请随时告诉我某些东西是糟糕的编码风格,但我只是文档编写者,而不是开发人员。)
反正我的情况是:
<items>
<item name="foo">
<coolThing>wah!</coolThing>
</item>
<item name="bar">
<needfulThing>address</needfulThing>
</item>
</items>
(当然是实际条款。)<coolThing>
元素只能出现在<item name="foo">
容器中,<needfulThing>
元素只能出现在[=16=中]容器。
如何在 XSD 中指定它?我正在查看的教程方便地忽略了这一点。
是否像将分类元素定义为属性声明的子元素一样简单:
<xs:attribute name="foo" type="xs:string">
<xs:element name="coolThing" type="xs:string"/>
</xs:attribute>
(为清楚起见,省略了一些内容。)当然,这不会让我轻易地指定 <coolThing>
可以同时出现在 <item name="foo">
和 <item name="baz">
元素中,如果出现这种情况。
还是我遗漏了什么? (很有可能。)
是的,您从根本上忽略了 XSD(以及其他 XML 模式)旨在将元素与基于 name[= 的类型相关联40=] 元素的属性,而不是元素的属性。
因此,使用 item
或 object
或 thing
等通过 name
等属性区分的过于通用的元素被视为反模式. XSD 1.1 有一个允许表达此类约束的断言机制,但实际上你会通过断言人为地重新实现自然包含约束——而不是你想要的地方。
具体来说,不是一般地设计 XML 元素,
<item name="foo"/>
让它们的元素名称传达它们的性质:
<foo/>
然后您会发现 XSD 1.0 中可用的普通内容模型足以表达您的包含限制。
更新:Michael Kay 让我想起了另一个 XSD 1.1 机制,它不如断言强大,但如果您只需要改变每个属性的类型,它更适合值:条件类型分配...
如果您坚持使用过于通用的元素名称并寻求在事后编写模式,在 XSD 1.1 的断言之前,请考虑 XSD 1.1 的 Conditional Type Assignment,它允许根据属性值分配类型。
可在此处找到完整的工作示例:
您可以使用 XSD 1.1 和 类型替代品 来执行此操作。参见示例 XSD 1.1 alternative usage issue。此功能明确设计用于执行您想要的操作 - 使元素的类型取决于属性的值,而不是元素的名称。
但是您需要 XSD 1.1 处理器。我知道三个:Altova、Saxon 和 Apache Xerces。许多广泛使用的 XSD 处理器,例如 Microsoft 的处理器,从未更新到 XSD 1.1。