Control attribute values order in RelaxNG

343 views Asked by At

Is it possible to control the order of the attribute values in Relax NG? which can be achieved using xs:assert in schema?

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>

The class value should be in order, paragraph1 should always come first and paragraph2 should come after paragraph1. The assert I tried in schema:

<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'))  "/>
1

There are 1 answers

11
sideshowbarker On BEST ANSWER

A (compact-syntax) RelaxNG grammar to express what the question describes could be written as:

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" } }

Expressed in the RelaxNG XML syntax:

<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>