下面是一个示例XML Schema。如您所见,我需要创建大量元素(elem001
到elem999
),其中所有元素都引用另一个元素" param"。请注意,param的属性ID是一个键,因此必须是唯一的。
现在,我如何指定限制,以便对elem001
,属性"数量"元素" param"只能采用一组给定的值。同样,elem002
到elem999
也有自己的一组值。然而,所有" param"整个XML文档中的元素必须具有唯一的ID。
我想如果我使用类型派生限制而不是ref,那么唯一性约束将不再适用于所有" param"亚型。那我该怎么办?
<xsd:element name="param">
<xsd:complexType>
<xsd:simpleContent base="xsd:double">
<xsd:extension>
<xsd:attribute name="quantity" type="xsd:string">
<xsd:attribute name="ID" type="xsd:int">
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:root>
<xsd:key name="paramkey">
<xsd:selector xpath="param/">
<xsd:field xpath="@ID">
</xsd:key>
<xsd:element name="elem001">
<xsd:element ref="param">
<xsd:element name="X" />
</xsd:element>
<xsd:element name="elem002">
<xsd:element ref="param">
<xsd:element name="Y" />
</xsd:element>
<!-- ... -->
<xsd:element name="elem999">
<xsd:element ref="param">
<xsd:element name="Y" />
</xsd:element>
</xsd:root>
--------------- EDIT ----------------
对不起,我应该提供一个我最终目标的示例XML文件,以使其更清晰。在下面的示例中,您可以看到我有几个对象(汽车,飞机,马)包含(除其他外)一些物理参数。属性&#34;数量&#34;定义我们所谈论的物理量:温度,燃料水平等。
现在,我有两个要求:
首先,我需要在我的架构中限制汽车允许的物理量,这显然不包括bloodPressure。同样,指定马的高度也没有意义(至少对我的应用来说......)。因此,我需要指定可以在汽车上测量的允许物理量。
其次,参数的id必须在所有参数中都是唯一的。例如,飞机高度的id不能为6,如果id为6(马的血压)的参数在&#34;数量&#34;
<car>
<param id="1" quantity="fuelLevel">100</param>
<param id="2" quantity="temperature">86</param>
</car>
<car>
<param id="3" quantity="fuelLevel">99</param>
<param id="4" quantity="temperature">77</param>
</car>
<horse>
<param id="5" quantity="temperature">123</param>
<param id="6" quantity="bloodPressure">26</param>
</horse>
<plane>
<param id="7" quantity="altitude">1000</param>
<param id="8" quantity="temperature">1050</param>
</plane>
实际上,如果我可以做类似下面的事情,它可能会更好,但我认为它更不可行。
<car>
<params>
<fuelLevel id="1">100</fuelLevel>
<temperature id="2">86</temperature>
</params>
</car>
<car>
<params>
<fuelLevel id="3">99</fuelLevel>
<temperature id="4">77</temperature>
</params>
</car>
<horse>
<params>
<temperature id="5">123</temperature>
<bloodPressure id="6">26</bloodPressure>
</params>
</horse>
<plane>
<params>
<temperature id="7">1000</temperature>
<altitude id="8"></altitude>
</params>
</plane>
另一个精度:我需要将唯一的id作为int,因此我不能使用与id和数量字段相关联的键。
顺便说一下,这个论坛不允许我提出一些问候或感谢表达,这令人非常不安。
答案 0 :(得分:0)
你写我想如果我使用类型派生限制而不是ref,那么唯一性约束将不再适用于所有“param”子类型。为什么你猜? (并且不会检查规范或要求验证器比猜测更有用吗?)
伪架构中的键约束适用于名为param
的范围元素的所有子元素,无论其类型如何;为什么会输入限制改变?
在任何情况下,不清楚类型限制和XSD身份约束在这里有任何关联:如果你想约束一组param
元素,给定元素可以指向不通过名称指向的元素,或者它在文档中的位置,但是基于所指向的quantity
元素的param
属性的值,你已经远远超出了基本XSD的表达能力类型构造函数,也超出了XSD身份约束的表达能力。 (此外,它的价值超出了关系数据库系统中引用完整性约束的可比性。)
XSD标识约束确保在文档中给定元素实例的范围内,在非常简单,可清晰流化的XPath 1.0子集中可识别的值或值序列的唯一性。
XSD类型定义总是被构造为允许以无上下文的方式孤立地对类型进行元素验证。没有类型级约束可以依赖于被验证的元素或属性之外的值 - 如果可以,那么将元素插入特定上下文,或者检索它并从其上下文中提取它的操作可能会改变其类型。向你最近的数据库或编程语言理论家询问他们的喜好,但要准备好在他们晕倒时抓住它们。
你的设计听起来非常糟糕,不必要,毫无意义。你几乎肯定会扔掉它并重新开始。它作为使用XML的设计并不好。
最多,它可能是一种练习,一种展示如何处理XSD情况的方法,如果你需要自己蒙上眼睛,把手放在口袋里,然后哼着Marseillaise跳一条腿而房间里的其他人则在你的耳朵里喊着达达的诗歌,并在你的脚下滑动香蕉皮。
本着这种精神,考虑以下XSD 1.1模式,该模式定义了一个符合您在散文中描述的要求的词汇表(并忽略了您的伪代码,因为我无法弄清楚它想要做什么)。
我们将元素root
,param
和elem001
定义为elem005
,将其他994定义为读者的练习。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/jacques"
xmlns:tns="http://example.com/jacques"
elementFormDefault="qualified">
<xs:element name="root" type="tns:root">
<xs:key name="parameter-uniqueness">
<xs:selector xpath=".//tns:param"/>
<xs:field xpath="@ID"/>
</xs:key>
</xs:element>
如您所见,根元素强制执行param/@ID
值的唯一性。
<xs:element name="param" type="tns:param"/>
<xs:element name="elem001" type="tns:elemNNN"/>
<xs:element name="elem002" type="tns:elemNNN"/>
<xs:element name="elem003" type="tns:elemNNN"/>
<xs:element name="elem004" type="tns:elemNNN"/>
<xs:element name="elem005" type="tns:elemNNN"/>
param
和elemNNN
元素不是很有趣。请注意,elem001
到elem005
都属于同一类型。类型限制在这里不是不可能的,但它也无助于达到你想要的效果。
<xs:complexType name="param">
<xs:simpleContent>
<xs:extension base="xs:double">
<xs:attribute name="quantity" type="xs:integer"/>
<xs:attribute name="ID" type="xs:int"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="elemNNN" mixed="false">
<xs:sequence>
<!--* Whatever common structure we want here *-->
<xs:any minOccurs="0" maxOccurs="unbounded"
processContents="lax"/>
</xs:sequence>
<xs:attribute name="param" type="xs:int" use="required"/>
<!--* Whatever common attributes we want ... *-->
<xs:attribute name="color"/>
<xs:attribute name="shape"/>
<xs:attribute name="height"/>
<xs:attribute name="postal-code"/>
<!--* ... *-->
</xs:complexType>
所有有趣的动作都是根元素的类型。它的内容模型很简单:一些参数然后是elemNNN
元素:
<xs:complexType name="root">
<xs:sequence>
<xs:element ref="tns:param" minOccurs="0"
maxOccurs="unbounded"/>
<xs:element ref="tns:elem001"/>
<xs:element ref="tns:elem002"/>
<xs:element ref="tns:elem003"/>
<xs:element ref="tns:elem004"/>
<xs:element ref="tns:elem005"/>
</xs:sequence>
由于param
元素位于指向元素之外,因此无法在指向元素的类型上表达给定元素可指向的param
元素的约束。 (如果它们是嵌入的,正如你的伪模式似乎暗示的那样,事情将会非常不同,但是不会涉及任何指向。)所以它们必须在一些具有指向元素和参数的祖先元素的声明中表达出来。元素作为后代。在这里,我们在根元素上进行。
我们允许elem001
仅指向param
属性介于-323和+2387之间的quantity
元素,包括:
<xs:assert test="for $e in .//tns:elem001,
$pref in $e/@param,
$p in .//tns:param[@ID = $pref],
$q in $p/@quantity
return
($q gt -324 and $q le 2387) (: in range -323 to 2398 :) "/>
允许元素elem002
仅指向其param
属性为小于15的正素数的quantity
元素:
<xs:assert test="for $e in .//tns:elem002,
$pref in $e/@param,
$p in .//tns:param[@ID = $pref],
$q in $p/@quantity
return
($q = (2, 3, 5, 7, 11, 13)) (: prime lt 15 :) "/>
elem003
上的约束是其param
元素的quantity
值必须等于0,1,7,8,14,15 ......:
<xs:assert test="for $e in .//tns:elem003,
$pref in $e/@param,
$p in .//tns:param[@ID = $pref],
$q in $p/@quantity
return
($q mod 7 lt 2) "/>
等等。
<xs:assert test="for $e in .//tns:elem004,
$pref in $e/@param,
$p in .//tns:param[@ID = $pref],
$q in $p/@quantity
return
($q gt 2387) "/>
<xs:assert test="for $e in .//tns:elem005,
$pref in $e/@param,
$p in .//tns:param[@ID = $pref],
$q in $p/@quantity
return
($q le -324)
"/>
</xs:complexType>
</xs:schema>
此架构接受以下输入为有效;通过使指针指向具有不适当param
属性的quantity
,或通过更改实际指向的quantity
元素上的param
值,很容易使其无效到。
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/jacques jacques.xsd"
xmlns="http://example.com/jacques">
<param ID="1" quantity="23">2</param>
<param ID="14" quantity="3">876.4</param>
<param ID="31" quantity="44423">833838</param>
<param ID="-44" quantity="23">111</param>
<param ID="-127" quantity="-0333">22223.33</param>
<param ID="22" quantity="8">2</param>
<param ID="12" quantity="23">1</param>
<elem001 param="1">
<p>This is some sample data.</p>
</elem001>
<elem002 param="14">
<p>Just hanging around here.</p>
</elem002>
<elem003 param="22">
<p>No worries.</p>
</elem003>
<elem004 param="31">
<p>How you doin', bro?</p>
</elem004>
<elem005 param="-127">
<p>Hasta la vista, baby.</p>
</elem005>
</root>