0

让我们假设使用这样的 xml 文档:

<Item>
  <Price>10</Price>
  <Ratio>1.5</Ratio>
  <MaxPrice>18<MaxPrice>
</Item>

<Item>
  <Price>12</Price>
</Item>

数据的含义是:一个项目必须有一个价格和可选的迭代价格变化的比率,以及一个不应超过的最高价格。澄清一下:只有 { Price} 或所有三个元素 { Price, Ratio, MaxPrice}。不允许其他选项。

通常,XSD 允许使用 使元素成为可选元素minOccurs="0",因此我们可以这样定义Item

<xs:element name="Item">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="Price" type="xs:integer" />
            <xs:element name="Ratio" type="xs:float" minOccurs="0" />
            <xs:element name="MaxPrice" type="xs:integer" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

但这还不够。这将使例如Item只有 {PriceRatio} 通过 - 这是不正确的。

如何才能做到这一点?

4

1 回答 1

0

xs:sequence和的结合xs:choice是这里的关键,请记住,将两者结合的方式很重要(见下文为什么)。正确的方法(至少基于我设法找出的)是像这样表达构建 XSD:

<xs:complexType name="itemType">
    <xs:sequence>
        <xs:element name="Price" type="xs:integer" />
        <xs:choice minOccurs="0">
            <xs:sequence>
                <xs:element name="Ratio" type="xs:float" />
                <xs:element name="MaxPrice" type="xs:integer" />
            </xs:sequence>
        </xs:choice>
    </xs:sequence>
</xs:complexType>

<xs:element name="Item" type="my:itemType" />

这样,您可以选择包含固定的元素序列,这正是我们所寻找的。

(如果你找到了你要找的东西,你可以在这里停止阅读。接下来的内容仅仅是解释似乎还有哪些其他方法以及为什么它们不起作用)

有人可能想知道(这也是我从其他地方启发的最初想法)两个固定序列的固定选择也可能起作用,并且可以作为一种广泛可重用的模式。尽管在某些情况下确实如此,但这并不是其中之一。观察:

<xs:complexType name="itemType">
    <xs:choice>
        <xs:sequence>
            <xs:element name="Price" type="xs:integer" />
        </xs:sequence>
        <xs:sequence>
            <xs:element name="Price" type="xs:integer" />
            <xs:element name="Ratio" type="xs:float" />
            <xs:element name="MaxPrice" type="xs:integer" />
        </xs:sequence>
    </xs:choice>
</xs:complexType>

<xs:element name="Item" type="my:itemType" />

看起来不错吧?好吧,显然不是 - 完整的项目不会通过!验证器迭代地落入第一选择,验证Price元素并失败,说明以下Ratio元素是意外的

好吧,一个明显的补救措施出现了 - 让我们切换选择:

<xs:complexType>
    <xs:choice>
        <xs:sequence>
            <xs:element name="Price" type="xs:integer" />
            <xs:element name="Ratio" type="xs:float" />
            <xs:element name="MaxPrice" type="xs:integer" />
        </xs:sequence>
        <xs:sequence>
            <xs:element name="Price" type="xs:integer" />
        </xs:sequence>
    </xs:choice>
</xs:complexType>

<xs:element name="Item" type="my:itemType" />

这似乎工作正常,直到您决定扩展可怜的Item元素(也许 Item 元素的其他一些用法也可能会导致麻烦)。

我试过例如:

<xs:complexType name="DiscountedItem">
    <xs:complexContent>
        <xs:extension base="my:itemType">
            <xs:sequence>
                <xs:element name="Discount" type="xs:integer" />
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

如果你尝试这个,你会在DiscountedItem有或没有 { Ratio, MaxPrice} 子元素的情况下失败,这取决于你是否切换了选择。

尽管如此,这得出的结论是,对于这个用例,使用第一个提到的“包含固定序列的可选选项”会更好。我发现这很难,所以你不必:)

于 2013-03-26T16:02:44.393 回答