XSD:向强类型“简单”元素添加属性

15

有没有一种明智的方法,可以既拥有强类型简单类型元素,又拥有属性?

好的,我有一个 XSD 架构,其中有一百万(嗯,几百个)可能看起来像这样的元素:

<xsd:element name="DocumentDescription" type="xsd:string" />
<xsd:element name="DocumentDateTime" type="xsd:dateTime" />
<xsd:element name="DocumentSize" type="xsd:int" />

这很不错。但是,我真的希望所有这些元素也有一些共同属性,比如“格式”和“isVisible”。也就是说,有一个像这样的模式:

<DocumentDescription isVisible="true">doc description</DocumentDescription>
<DocumentDateTime format="dd/mm/yyyy" isVisible="true">1/1/2008</DocumentDescription>
<DocumentSize format="0.00 KB" isVisible="false">5403</DocumentSize>

我可以手动地完成这个过程,但会非常麻烦,需要在生成XSD时将所有这些属性添加到其中,就像这样:

<xsd:element name="DocumentDescription" />
  <xsd:complexType>
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="format" type="xsd:string" />
        <xsd:attribute name="isVisible" type="xsd:boolean" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>
<xsd:element name="DocumentDateTime" />
   ... etc

...但在理想的情况下,我更愿意将其定义为complexType:

<xsd:complexType name="customType">
  <xsd:complexContent>
    <xsd:extension base="???">
      <xsd:attribute name="format" type="xsd:string" />
      <xsd:attribute name="isVisible" type="xsd:boolean" />

这意味着我可以只需要做:

<xsd:element name="DocumentDescription" type="customType" baseType="xsd:string" />
<xsd:element name="DocumentDateTime" type="customType" baseType="xsd:dateTime" />
<xsd:element name="DocumentSize" type="customType" baseType="xsd:int" />

我的“理想世界”代码的问题是:

a) 我没有有效的<xsd:extension base-"???">,因为我真的不关心我正在扩展什么; 我想要扩展所有类型。看起来"xsd:anyType"是适当的,但那么元素不就变成了弱类型容器了吗?

b) 我不能再在<xsd:element>上指定简单类型,因为现在类型是我定义的复杂的“customType”。因此,我在那里放置的虚构“baseType”属性...

所以我能否以不笨重的方式向简单类型添加属性?还是我需要定义十几个除了扩展的简单类型外都相同的复杂类型?

强类型元素不仅更合理地描述数据,而且当我将它们用于Excel中的XML映射(这正是这些东西背后的全部目的)时,强类型意味着Excel根据类型正确设置单元格格式。

我可能完全错了!任何建议都将不胜感激。


我取消了一次编辑,该编辑包括将所有“强类型”出现更名为“内置简单类型”(W3C措辞)。这样的措辞本来会帮助我找到你的问题。现在我不确定这个修改是否值得,我很满意我的评论包括这个措辞,所以我可以在将来再次找到你的问题。 - Alberto
3个回答

4

不太清楚您认为手动解决方案的哪个方面很糟糕;如果是因为必须定义 n 种不同类型,仅因为它们需要扩展 n 种不同的基础类型,那么您就处于困境中。

如果您认为必须有 n 种不同的声明来处理 formatisVisible 属性的想法很可怕,那么您可以使用命名属性组来保存这些定义,这样可能会更容易理解:

<xs:attributeGroup name="globals">
  <xs:attribute name="format" type="xs:string"/>
  <xs:attribute name="isVisible" type="xs:boolean"/>
</xs:attributeGroup>

各种复杂类型的声明仍然重复,但现在略微简洁了一些。
<xs:complexType name="string">
  <xs:simpleContent>
    <xs:extension base="xs:string">
      <xs:attributeGroup ref="my:globals"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>
<xs:complexType name="dateTime">
  <xs:simpleContent>
    <xs:extension base="xs:dateTime">
      <xs:attributeGroup ref="my:globals"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>
<xs:complexType name="int">
  <xs:simpleContent>
    <xs:extension base="xs:int">
      <xs:attributeGroup ref="my:globals"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>

现在,您元素的声明比您的“理想”情况稍微简单了一些:

<xs:element name="DocumentDescription" type="my:string" />
<xs:element name="DocumentDateTime" type="my:dateTime" />
<xs:element name="DocumentSize" type="my:int" />

在XSD 1.1中,有一个名为defaultAttributes的模式属性,它将属性组应用于每个complexType,除非在该complexType中设置了defaultAttributesApply为false。这对于simpleTypes不起作用,但是使用您的出色方法,您可以为每个complexType声明少写两行代码,因为扩展可以是自封闭标签<xs:extension base="xs:string"/> - sergioFC

3

[quote]可以手动完成,但方法很糟糕,需要在生成XSD时将所有这些属性添加到其中,类似于这样:[/quote]

恐怕这是你唯一“正确”的、符合XSD-schema的做法。

有时候编写XSD可能会很复杂 - 但它可以保证事情的安全性 :-)

Marc


该死!好吧,谢谢。不过我可能会先尝试一下十二个除扩展类型外完全相同的复杂类型,考虑到元素数量,它至少会使 XSD 更小,尽管难看! - Gavin
1
@Gavin 如果你总是添加相同的属性集,那么建议查看C. M. Sperberg-McQueen提出的attributeGroup。这值得一看。 - Alberto

1
XSD的目的是描述您的数据。 XSD的类型属性的目的是描述或定义元素。 您想要做的是更改元素的定义。 如果您正在更改描述,请更改类型。 您要做的就像在思想上安装车轮一样。 “但我想要我的思想上有车轮!” “抱歉,无法实现。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接