【问题标题】:Generating XSD from RelaxNG while keeping root-element restriction从 RelaxNG 生成 XSD,同时保持根元素限制
【发布时间】:2018-04-12 13:03:28
【问题描述】:

我想将以下架构从 RNC/RNG 转换为 W3C XSD。

default namespace = ""
namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
namespace rng = "http://relaxng.org/ns/structure/1.0"

start = starting_risk

starting_risk =
  element risk {
    element continents { Continents }?
  }

Continents = element continent { Continent }+
Continent =
  element country { Country }*,
  element sea { Sea }*
Country = xsd:string { minLength = "1" maxLength = "100" }
Sea = xsd:string { minLength = "1" maxLength = "100" }

使用 trang,我最终得到了

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="risk">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" ref="continents"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="continents" type="Continents"/>
  <xs:complexType name="Continents">
    <xs:sequence>
      <xs:element maxOccurs="unbounded" ref="continent"/>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="continent" type="Continent"/>
  <xs:complexType name="Continent">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" ref="country"/>
      <xs:element minOccurs="0" maxOccurs="unbounded" ref="sea"/>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="country" type="Country"/>
  <xs:element name="sea" type="Sea"/>
  <xs:simpleType name="Country">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="100"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="Sea">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="100"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

问题是层次结构丢失了。 “风险”元素是模式的根,也是该级别唯一有效的元素。在 RNC 中,“风险”和“大陆”元素之间的关系是父子关系。但在 XSD 中,它们是兄弟姐妹。我做错了什么/我不明白吗?

【问题讨论】:

    标签: xsd relaxng relaxng-compact root-element


    【解决方案1】:

    你没有做错任何事。我认为不幸的是,您不能使用 trang 从您的 RNC 架构生成 XSD,以保留对允许作为根元素的限制。

    您可以改为手动创建一个 XSD,限制为只有 risk 是唯一的 global element,其余所有元素都是 local element。但是(据我所知)您无法使用trang 生成这样的 XSD。原因是(至少据我所知)trang 基本上总是只生成带有全局元素的 XSD。

    如果您像这样编写 RNC,您可能会认为可以使用本地元素生成 XSD:

    start =
    element risk {
      element continents {
        element continent {
          element country { xsd:string { minLength = "1" maxLength = "100" } }*,
          element sea { xsd:string { minLength = "1" maxLength = "100" } }*
        }+
      }?
    }
    

    这基本上与您手动构建 XSD 的方式相同。

    但是,如果您通过 trang 运行它以生成 XSD,您会发现每个元素都作为生成的 XSD 中的全局元素出现。这就是trang 一直这样做的方式。

    因此,除非我不知道有什么神奇的方法可以强制 trang 否则,如果您想将 XSD 架构限制为仅允许 risk 作为根元素,那么您唯一的选择是创建 XSD手动。

    我猜这可能被视为 trang 中的设计缺陷,但可以说真正的问题是 XML Schema 的设计与 RelaxNG 的 start 没有任何相似之处来显式指定根元素。

    如果 XML Schema 确实有类似 RelaxNG 的 start 的简单方法来指定允许作为根元素的内容,那么 trang 可以将其输出到 XSD 中,你就会得到你想要的。

    但是因为 XSD 没有像 start 这样的东西,所以将架构限制为只有一个特定根元素的唯一机制是将 XSD 完全(重新)构造成 “local style”

    但是,如本答案前面所述,很遗憾,您无法使用 trang 从 RelaxNG 源生成这种“本地风格”的 XSD。您必须手动单独创建 XSD。

    可以想象trang 理想情况下可以设计一些选项以允许您生成“本地样式”XSD,或者可能使用一些启发式方法以某种方式推断出它应该使用的输出样式。但现实情况是,trang 的实际运作方式并非如此,而且不会改变。

    因此,虽然我确定这不是您希望得到的答案,但我希望它有助于澄清问题。

    【讨论】:

    • 非常有用的链接,谢谢。您认为使用 XSL 可以实现全局表单和本地表单之间的转换吗?
    • 是的,绝对有可能编写一个 XSL 样式表,从您的 RNC 源获取 trang 的 XSD 输出并将其转换为风险元素是唯一全局元素的 XSD。所以我建议你尝试编写一个 XSL 样式表来完成它。然后稍后在 SO 上发布一个单独的后续问题 - 如果/当您遇到无法解决的 XSLT 问题时,或者如果您自己解决了问题,您可以同时发布一个问题和一个答案(例如,问题:“如何使用 XSLT 将 trang 的全局样式 XSD 输出转换为本地样式?”)。
    猜你喜欢
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    相关资源
    最近更新 更多