Порядок значений атрибутов управления в RelaxNG

Можно ли контролировать порядок значений атрибутов в Relax NG? чего можно добиться, используя xs:assert в схеме?

XML:

<body>
 <h1 class="title">title</h1>
 <h2 class="subtitle">subtitle</h2>
 <p class="paragraph1">para text 1</p>
 <p class="paragraph2">Para text 2</p>
 <p class="paragraph3">Para text 2</p>
 </body>

Значение класса должно быть в порядке, абзац 1 всегда должен стоять первым, а абзац 2 — после абзаца 1. Утверждение, которое я пробовал в схеме:

<xs:assert test="p[1]/@class = 'paragraph1'
and ((every $i in p[2] satisfies $i/@class = 'paragraph2')
and (every $i in p[3] satisfies $i/@class = 'paragraph3'))  "/>

person VSr    schedule 17.05.2017    source источник


Ответы (1)


Грамматика (компактный синтаксис) RelaxNG для выражения того, что описывает вопрос, может быть записана как:

start = element body { h1?, h2?, p.paragraph1?, p.paragraph2?, p.paragraph3? }
h1 = element h1 { text & attribute class { string } }
h2 = element h2 { text & attribute class { string } }
p.paragraph1 = element p { text & attribute class { string "paragraph1" } }
p.paragraph2 = element p { text & attribute class { string "paragraph2" } }
p.paragraph3 = element p { text & attribute class { string "paragraph3" } }

Выражено в синтаксисе XML RelaxNG:

<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="">
  <start>
    <element name="body">
      <optional>
        <ref name="h1"/>
      </optional>
      <optional>
        <ref name="h2"/>
      </optional>
      <optional>
        <ref name="p.paragraph1"/>
      </optional>
      <optional>
        <ref name="p.paragraph2"/>
      </optional>
      <optional>
        <ref name="p.paragraph3"/>
      </optional>
    </element>
  </start>
  <define name="h1">
    <element name="h1">
      <interleave>
        <text/>
        <attribute name="class">
          <data type="string"/>
        </attribute>
      </interleave>
    </element>
  </define>
  <define name="h2">
    <element name="h2">
      <interleave>
        <text/>
        <attribute name="class">
          <data type="string"/>
        </attribute>
      </interleave>
    </element>
  </define>
  <define name="p.paragraph1">
    <element name="p">
      <interleave>
        <text/>
        <attribute name="class">
          <value type="string">paragraph1</value>
        </attribute>
      </interleave>
    </element>
  </define>
  <define name="p.paragraph2">
    <element name="p">
      <interleave>
        <text/>
        <attribute name="class">
          <value type="string">paragraph2</value>
        </attribute>
      </interleave>
    </element>
  </define>
  <define name="p.paragraph3">
    <element name="p">
      <interleave>
        <text/>
        <attribute name="class">
          <value type="string">paragraph3</value>
        </attribute>
      </interleave>
    </element>
  </define>
</grammar>
person sideshowbarker    schedule 17.05.2017
comment
Спасибо. Элемент p нужно объявлять каждый раз? Тогда релаксNG будет длительным, если мы рассмотрим сложную структуру? Есть ли другие варианты? - person VSr; 17.05.2017
comment
Для выражения ограничения, которое вам нужно в RelaxNG, я не знаю других вариантов, кроме объявления нескольких элементов p, как это делает ответ. В схеме RelaxNG для HTML5 github.com/validator/validator/tree/master/ schema/html5, где мне нужно было указать аналогичные ограничения, я использовал тот же шаблон, описанный в ответе, то есть объявление элемента несколько раз в грамматике, каждый из которых имеет другое значение обязательного атрибута. . Да, я предполагаю, что это относительно многословно, но, по крайней мере, в компактном синтаксисе оно намного менее многословно по сравнению с выражением в XML. - person sideshowbarker; 17.05.2017
comment
Привет, посетитель, я пытался использовать тот же RNC, что и html5, из Nu, но получаю ошибку dataLibrary в jing. Можно ли использовать этот RNC и настроить их по моему требованию? - person VSr; 17.05.2017
comment
@Senthil Я думаю, вы хотите задать отдельный новый вопрос с RNC, который вы пытаетесь, и сообщение об ошибке - person sideshowbarker; 17.05.2017
comment
Насыщенный абзац 2 ОП должен идти после абзаца 1. Однако предложенная здесь схема позволяет <p class="paragraph2"> быть первым элементом p в body и, таким образом, ему не должен предшествовать элемент, отмеченный классом paragraph1. Возьмите пример XML OP и удалите первый элемент p, и он будет проверен. Мне кажется, что это не только порядок, который ОП пытается выполнить, но и последовательная последовательность, начинающаяся с 1. @Senthil, пожалуйста, ответьте. - person Louis; 17.05.2017
comment
Привет, Луи, предложенная схема допускает ‹p class=paragraph2› даже отсутствие параграфа 1, потому что все p объявлены необязательными. Если мы возьмем «необязательный» перед каждым p, то сначала будет запрашиваться абзац 1. - person VSr; 18.05.2017
comment
@sideshowbarker, я попытался ограничить RNC с помощью опции чередования и попробовал что-то вроде start = element body { h1?, h2?, p.paragraph1+ & p.paragraph2? & п.параграф3? } сделать пункт 1 обязательным, а 2 и 3 сделать где угодно. Но я столкнулся с ошибкой p может встречаться более чем в одном операнде чередования. Есть ли способ сделать это? - person VSr; 22.05.2017
comment
VSR сделал то, что вы пробовали, не работает? Что бы вам ни нужно было сделать, я почти уверен, что это можно выразить с помощью RelaxNG, хотя, как указал @Louis, это может быть сложнее, чем то, что в этом ответе. И это может оказаться относительно подробным - person sideshowbarker; 22.05.2017
comment
<body> <h1 class="title">title</h1> <h2 class="subtitle">subtitle</h2> <p class="paragraph2">Para text 2</p> <p class="paragraph1">para text 1</p> <p class="paragraph3">Para text 2</p> ‹/тело› - person VSr; 22.05.2017
comment
VSr OK, я предлагаю опубликовать это как отдельный вопрос. Это лучший способ привлечь внимание большинства людей и максимально быстро получить лучший ответ. - person sideshowbarker; 22.05.2017
comment
@sideshowbarker, да, я создал один stackoverflow.com/questions/44111198/interleave-in-rnc - person VSr; 22.05.2017