从RelaxNG生成XSD,同时保持根元素限制

时间:2018-04-12 13:03:28

标签: xsd relaxng relaxng-compact root-element

我想将以下架构从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>

问题是层次结构丢失了。 'risk'元素是模式的根,是该级别唯一有效的元素。在RNC中,'risk'和'continent'元素之间的关系是父对子。但在XSD中,他们是兄弟姐妹。我做错了什么/我不理解?

1 个答案:

答案 0 :(得分:2)

你没有做错任何事。我想很遗憾你不能使用trang从你的RNC架构生成一个XSD,它保留了对作为根元素允许的限制。

您可以手动创建限制为riskglobal element的XSD,其余所有元素均为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实际运作的方式,也不会改变。

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