Генерация XSD из RelaxNG с сохранением ограничений корневых элементов

Я хочу преобразовать следующую схему из 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 является корнем схемы и единственным действительным элементом на этом уровне. В СРН отношения между элементами "риск" и "континент" являются родительскими и дочерними. Но в XSD они братья и сестры. Что я делаю не так / я не понял?

1 ответ

Решение

Вы не делаете ничего плохого. Я думаю, к сожалению, вы просто не можете использовать trang генерировать XSD из вашей схемы RNC, которая сохраняет ограничение на то, что разрешено в качестве корневого элемента.

Вместо этого вы можете вручную создать XSD, ограниченный risk быть единственным глобальным элементом со всеми остальными элементами, каждый из которых является локальным элементом. Но (насколько я знаю) вы не можете создать такой XSD, используя trang, Причина в том (опять же, насколько я знаю, по крайней мере) trang в основном всегда генерирует XSD только с глобальными элементами.

Вы можете подумать, что можете сгенерировать XSD с локальными элементами, если вы напишите свой RNC следующим образом:

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-схемы был такой же простой способ, как у RelaxNG start указать, что разрешено в качестве корневого элемента, затем trang можно просто вывести это в XSD, и вы получите то, что хотите.

Но потому что XSD не имеет ничего общего startваш единственный механизм ограничения вашей схемы наличием только одного конкретного корневого элемента - полностью (ре) структурировать ваш XSD в "локальный стиль".

Однако, как упоминалось ранее в этом ответе, вы, к сожалению, не можете сгенерировать XSD "локального стиля" из источников RelaxNG, используя trang, Вместо этого вы должны отдельно создать XSD вручную.

Это мыслимо trang в идеале можно было бы разработать какую-то опцию, чтобы позволить вам генерировать XSD "локального стиля", или, возможно, с некоторой эвристикой, чтобы каким-то образом сделать вывод, когда этот стиль вывода следует использовать. Но реальность такова, что это не так trang на самом деле работает, и это не изменится.

Поэтому, хотя я уверен, что это не тот ответ, который вы надеялись получить, я надеюсь, что это поможет прояснить ситуацию.

Другие вопросы по тегам