【问题标题】:How do I extend the Atom schema?如何扩展 Atom 模式?
【发布时间】:2023-03-17 06:56:01
【问题描述】:

我正在设计一个 XML 产品提要,许多网店将使用它来发布他们的产品数据。此产品 Feed 的结构将基于 Atom XML standard,类似于 Google's Atom product feed。我将发布一个 XSD 文件,可用于验证产品提要。

基本上,每个<entry> 元素将代表一个产品。我需要向<entry> 元素添加一些子元素,其中将包含产品价格、运费等数据。

问题在于创建 XSD 文件。我不确定如何扩展 Atom 标准,以便可以将子元素添加到 <entry>。目前我只是将额外元素定义为顶级元素,但这不允许我指定出现指示器(minOccursmaxOccurs)。

我想要做的是指定每个<entry> 元素中所需的元素数量。它们可以是我的架构引入的新元素(例如包含产品价格的 <price> 元素),也可以是现有的 Atom 元素(例如由 Atom 定义但不是必需的 <link> 元素) .

这是我当前的 product-feed.xsd(简化版):

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://example.com/schemas/product-feed"
    xmlns:p="http://example.com/schemas/product-feed"
    xmlns:atom="http://www.w3.org/2005/Atom"
    elementFormDefault="qualified">

  <xs:element name="brand" type="xs:string" />

  <xs:element name="price" type="p:money" />

  <xs:element name="shipping" type="p:money" />

  <xs:complexType name="money">
    <xs:simpleContent>
      <xs:extension base="xs:decimal">
        <xs:attribute name="currency" 
                      type="p:currency" 
                      use="required" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:simpleType name="currency">
    <xs:restriction base="xs:string">
      <xs:enumeration value="EUR" />
      <xs:enumeration value="USD" />
      <xs:enumeration value="GBP" />
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

这是一个示例 xml 提要:

<?xml version="1.0" encoding="UTF-8"?>

<feed xmlns="http://www.w3.org/2005/Atom"
      xmlns:p="http://example.com/schemas/product-feed"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <title>Example Store</title>
  <link href="http://www.example-store.com/" rel="self" />
  <updated>2014-08-08T10:44:20Z</updated>

  <entry>
    <title>Foo</title>
    <link href="http://www.example-store.com/products/foo.html" />
    <p:price currency="EUR">32.95</p:price>
    <p:shipping currency="EUR">6.75</p:shipping>
  </entry>

  <entry>
    <title>Bar</title>
    <link href="http://www.example-store.com/products/acme-bar.html" />
    <p:brand>Acme</p:brand>
    <p:price currency="EUR">12.50</p:price>
    <p:shipping currency="EUR">6.75</p:shipping>
  </entry>

</feed>

如何扩展 Atom 架构,使我的自定义元素只允许在 &lt;entry&gt; 元素内,并且我可以定义它们可能出现的次数?

我能想到的唯一替代解决方案是复制一个 Atom 模式定义文件(例如 this one),然后对其进行修改(添加我自己的元素,并更改我想要的 Atom 元素)。这感觉不太好(我不会再扩展 Atom,我只会创建一个全新的模式)所以我希望有更好的解决方案。

【问题讨论】:

  • 您只是想要一个 XSD 架构来验证您​​的数据,还是需要它为 Atom 命名空间合并一些现有的 XSD 架构?如果是后者,那么您希望使用 Atom 命名空间的现有 XSD 架构吗?
  • 您说“将额外元素定义为顶级元素......允许它们在任何地方使用,而不仅仅是在 &lt;entry&gt; 元素内”,这表明您不希望它们在&lt;entry&gt; 之外有效,覆盖Atom 模式的规则,即它们在其他地方 有效。对于 Atom 模式,您还想强制执行哪些其他限制?您要编写的架构还有哪些其他要求?
  • @C.M.Sperberg-McQueen 据我所知,Atom 标准没有权威的 XSD 架构,但我确实找到了 this one。我不需要扩展现有模式,但我更愿意这样做,而不是在我自己的 XSD 中复制所有内容。你是对的,Atom 允许在多个地方添加额外的元素。但是,例如,我希望能够要求每个 元素包含一个 元素(我引入的自定义元素)和一个 元素(由 Atom 定义,但不是必需的)。请参阅我更新的问题。

标签: xml xsd atom-feed


【解决方案1】:

一个完整的答案和解释需要比我今天更多的时间,但可以快速勾勒出解决方案的要点。

首先,您指向的 XSD 作为 RFC 4287 中所述的 Atom 格式的表示存在许多问题。

  • 它使用重复的选择组来表示 Relax NG 交错组,这意味着它不强制规范 RNG 模式的任何基数约束,在 Atom person 构造中,atom:feed 元素,atom:entry 元素,或 atomSource。

在 XSD 1.1 架构中,最好使用所有组来表示这些。在 XSD 1.0 架构中,对单个元素实施最小和最大出现约束将需要对序列进行相当冗长的选择(它们本身具有嵌套的选择组),这是可行的,但构建起来有些乏味。

  • 它对电子邮件地址使用正则表达式模式,既不符合 Atom 规范的散文(即地址必须符合 RFC 2922)也不符合 RNG 模式(使用非常简单的表达式 ".+@.+"

生成与 RFC 2822 的 addr-spec 产生匹配的正则表达式并因此强制执行 Atom 规范的规则是不可能的。 (合法的 addr-spec 值的集合是上下文无关的,而不是规则的,因为 RFC 2822 cmets 嵌套。)用正则表达式逼近它是可能的,但有点耗时且容易出错,除非你系统地这样做。最简单的解决方案是遵循 Atom 规范中的 RNG 模式示例,并且只需要一个在开头和结尾都至少包含一个 at 符号的字符串。

因此,您的第一步是创建(或查找)一个 XSD,它可以更好地表示 Atom 文档语法。

那么你的三个选择是:

  • 修改架构文档(添加 cmets 来描述您的更改,并将未来的读者指向您从其开始的基本架构文档)以导入您的命名空间并将您想要的特定元素添加到 atom:entry 的内容模型。李>

这样做的好处是简单。它的缺点是,您对 Atom 语言的修改与其在 Atom 规范中的定义之间的关系仅在您的自然语言 cmets 所做的那样清晰。您担心在这种情况下您并没有真正扩展 Atom 语言;我认为您正在扩展 Atom 语言,但您正确地注意到您并没有通过为 Atom 扩展独立的 schema 来这样做。这可能算作一个劣势。

  • 使用 xsd:redefine 重新定义 atom:entry 元素的类型,方法是将通配符限制为您想要查看的元素。您的重新定义必须是基本模式中定义的类型的有效限制(但 XSD 不保证符合模式的符合重新定义将是符合模式,这使得重新定义的约束对某些用户来说似乎毫无意义)。

这具有符合 XSD 1.0 的优点;它的缺点是可能相当棘手且容易出错(就在上周,我听到一位著名的文档设计师在公开场合说他从未能够让 XSD 重新定义工作)。它还有一个缺点,即已知 XSD 1.0 处理器具有不一致的重新定义实现。 (但应注意,不一致主要出现在涉及多个冗余导入、包含和重新定义的情况下,不应出现在您描述的直接情况中)。

  • 如果您可以使用 XSD 1.1,请根据需要使用 xsd:override 修改 atom:entry 的内容模型。

这样做的好处是将您的更改与基本架构分开,并且比 xsd:redefine 更易于指定。但是,它确实需要 XSD 1.1,您希望使用的工具链可能支持也可能不支持。

【讨论】:

  • 感谢您的出色回答。我相信我的 IDE 使用 XSD 1.0,但我还不知道我将使用哪些其他工具来验证 XML 提要,所以恐怕我不能依赖可用的 XSD 1.1。我开始怀疑扩展 Atom 是否真的值得所有这些麻烦,我可能应该只创建自己的独立模式,而不扩展 Atom。尽管如此,您还是为我提供了一些宝贵的见解,非常感谢。
猜你喜欢
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
  • 2019-03-05
  • 2018-06-05
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
  • 2018-12-09
相关资源
最近更新 更多