如何为 XSD 中的数据库表建模?

How to model database tables in XSD?

为地址建模 table 似乎很简单,就像在 XSD:

中这样
  <xsd:complexType name="address_Type">
    <!-- the columns of the database table for addresses -->
    <xsd:sequence>
      <xsd:element name="street" type="xsd:string" />
      <xsd:element name="city" type="xsd:string" />
      <xsd:element name="state" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>

然后你可以定义一个 XML 格式,使用这个表格加上一些其他不相关的数据,比如用户名,像这样:

  <xsd:element name="user" type="user" />
  <!-- =========================================== -->
  <xsd:complexType name="user">
    <xsd:sequence>
      <!-- username stands for all non-address fields -->
      <xsd:element name="username" type="xsd:string" />
      <!-- wrapper element for the address fields -->
      <xsd:element name="address" type="address_Type" />
    </xsd:sequence>
  </xsd:complexType>

而 XML 可能是这样的:

<?xml version="1.0" encoding="utf-8"?>
<user>
  <username>Albert Einstein</username>
  <!-- with wrapper element for address -->
  <address>
    <street>Main Street</street>
    <city>Ghost Town</city>
    <state>Up State</state>
  </address>
</user>

此方法很容易扩展到 XML 的地址列表,或者地址记录与其他 table 的记录相结合。一个 XSD 可以通过这种方式覆盖很多 XML 格式。

但是,有人会想,如果我只包含地址对象的 1 个实例,为什么我需要那个愚蠢的“地址”包装器元素才能达到此 XML:

<?xml version="1.0" encoding="utf-8"?>
<user>
  <username>Albert Einstein</username>
  <!-- no wrapper element for address -->
  <street>Main Street</street>
  <city>Ghost Town</city>
  <state>Up State</state>
</user>

对我来说,现在我们似乎不能使用与上面 XSD 相同的地址复杂类型。

在我的公司,IT 组织是分散的,如果我开始大喊“你应该添加包装器元素”,我可能会喉咙痛。或者头痛。所以我要改进我的 XSD 以应对 XML 有无包装元素。

我试图添加一个没有名字的 xsd:element,但这不起作用:

<xsd:element type="address_Type" />

我找不到 xsd: 具有类型属性以指向除 xsd:element 以外的复杂类型的实体。

我的问题是是否还有方法可以为最后一个 XML 重新使用 complexType?

如果您希望在没有包装元素的情况下从现有内容模型中组合新的内容模型,请考虑使用 xs:group 机制:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:element name="user" type="user" />

  <xsd:complexType name="user">
    <xsd:sequence>
      <xsd:element name="username" type="xsd:string" />
      <!-- 
         ...
         Many more xsd:element or xsd:groups might appear here.
         ...
      -->
      <xsd:group ref="address"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:group name="address">
    <xsd:sequence>
      <xsd:element name="street" type="xsd:string" />
      <xsd:element name="city" type="xsd:string" />
      <xsd:element name="state" type="xsd:string" />
    </xsd:sequence>
  </xsd:group>  

</xsd:schema>

如果你想允许可选的包装器,你可以使用 xsd:choice:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="user" type="user" />

  <xsd:complexType name="user">
    <xsd:sequence>
      <xsd:element name="username" type="xsd:string" />
      <xsd:choice>
        <xsd:group ref="address"/>
        <xsd:element name="address">
          <xsd:complexType>
            <xsd:group ref="address"/>
          </xsd:complexType>
        </xsd:element>
      </xsd:choice>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:group name="address">
    <xsd:sequence>
      <xsd:element name="street" type="xsd:string" />
      <xsd:element name="city" type="xsd:string" />
      <xsd:element name="state" type="xsd:string" />
    </xsd:sequence>
  </xsd:group>  

</xsd:schema>

根据 kjhughes 的回答,我扩展了我的 XSD 以适应 XML 有无包装元素:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="usera" type="usera" />
  <xsd:element name="userb" type="userb" />
  <!-- ==== xml format without wrapper element ==== -->
  <xsd:complexType name="usera">
    <xsd:sequence>
      <xsd:element name="username" type="xsd:string" />
      <xsd:group ref="address_Group" />
    </xsd:sequence>
  </xsd:complexType>
  <!-- === xml format with wrapper element ==== -->
  <xsd:complexType name="userb">
    <xsd:sequence>
      <xsd:element name="username" type="xsd:string" />
      <xsd:element name="address">
        <xsd:complexType>
          <xsd:group ref="address_Group" />
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
  <!-- ==== database record type for table Address ==== -->
  <xsd:group name="address_Group">
    <xsd:sequence>
      <xsd:element name="street" type="xsd:string" />
      <xsd:element name="city" type="xsd:string" />
      <xsd:element name="state" type="xsd:string" />
    </xsd:sequence>
  </xsd:group>
</xsd:schema>

它可以在没有包装元素的情况下验证这个 XML:

<?xml version="1.0" encoding="utf-8"?>
<usera>
  <username>Albert Einstein</username>
  <!-- without address tag -->
  <street>Main Street</street>
  <city>Ghost Town</city>
  <state>Up State</state>
</usera>

还有这个 XML 和包装元素:

<?xml version="1.0" encoding="utf-8"?>
<userb>
  <username>Albert Einstein</username>
  <!-- with address tag -->
  <address>
    <street>Main Street</street>
    <city>Ghost Town</city>
    <state>Up State</state>
  </address>
</userb>

在XSD中所有的数据库记录只有一个描述table。我检查了这是否适用于使用 XSD.EXE 创建 C# 类 和反序列化。