递归XML的XSD架构

时间:2010-03-22 11:11:39

标签: xml xsd

我在为某些xml创建XSD时遇到了问题。

一些背景可能会有所帮助。 xml用于消息传递。特别是消息 设计简单,易于交叉引用。在它的核心 是一个递归键值设置。

简单键值就是这样。

    <key name="quantity">5</key>
    <key name="price" representation="percentage">99.78</key>

信息中有一个可选的表示属性 可以用两种不同的形式表示。

参考键值如下

    <key name="currency" reference="instrument">
        <id name=" INSID" system="XXXX" instance="PROD">DEM</id>
        <id name=" EXTERN_ID1" system="XXXX" instance="PROD"> ext128k</id>
    </key>

此表单用于外键引用或枚举引用。 交叉引用服务将选择具有引用属性的所有键。 然后它将获得该引用的所有可能ID,并添加额外的id 字段,并用新版本替换该子元素。

即“./key[@reference]”作为Xpath可以获取所有枚举和引用 来自xml

最后有一个递归结构。这里是键值的值部分, 可以是一个关键价值。

<key name="trade" type="trade">
    <key name="value_day">1999-03-12</key>
    <key name="quantity">5</key>
    <key name="leg" type="leg">
        <key name="rate">5.00</key>
        <key name="period">3m</key>
        <key name="cashflows" type="cashflows">
            <key name="cashflow">10</key>
            <key name="cashflow">20</key>
        </key>
    </key>
</key>

现在,我在为这种结构创建XSD时遇到了麻烦。

有人可以帮忙吗?

由于

尼克

1 个答案:

答案 0 :(得分:2)

如果我理解正确,您希望您可以像这样编写Schema:

<!-- WARNING: this is not valid Schema -->
<xs:complexType name="composite-key">
  <xs:choice maxOccurs="unbounded">
    <xs:element name="key" type="simple-key"/>
    <xs:element name="key" type="composite-key"/>
  </xs:choice>
  <xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>

简单密钥将在别处定义。这不是有效的架构,因为不允许两次使用相同的元素名称。如果Schema支持这一点,那么根据它们的结构,它将有一段时间消除歧义元素类型。

如果您可以控制XML,则可以通过更改一个或两个元素名称来完成此工作。例如,可以将 val 用于简单值,将 obj 用于复合值:

<xs:complexType name="composite-key">
  <xs:choice maxOccurs="unbounded">
    <xs:element name="val" type="simple-key"/>
    <xs:element name="obj" type="composite-key"/>
  </xs:choice>
  <xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>

根据品味调整名称。这是我推荐的解决方案,因为它强调清晰度。但是,元素名称可能不受您的控制。如果是这样,一个不太令人满意的解决方案如下:

<xs:complexType name="key" mixed="true">
  <xs:sequence maxOccurs="unbounded">
    <xs:element name="key" type="key"/>
  </xs:sequence>
  <xs:attribute name="name" type="xs:string" use="required"/>
  <xs:attribute name="type" type="xs:string"/>
  <xs:attribute name="representation" type="xs:string"/>
</xs:complexType>

这里的主要区别是混合内容类型,以及声明现在是简单和复合键类型的混合的不幸事实。我说这是“不太令人满意”,因为现在你必须在Schema完成它之后在你自己的代码中执行额外的有效性检查。例如,您需要验证给定的属性集是否对隐含的键类型有意义。此外,编写的示例将允许文本出现在嵌套的键元素之间的任何位置 - 可能是您不想要的。

[编辑:在stackoverflow here上讨论了同样的问题]