【问题标题】:Control attribute values order in RelaxNG在 RelaxNG 中控制属性值顺序
【发布时间】:2017-10-16 09:24:15
【问题描述】:

Relax NG中是否可以控制属性值的顺序?在 schema 中使用 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>

class 值应该是有序的,paragraph1 应该总是在前面,paragraph2 应该在paragraph1 之后。我在架构中尝试过的断言:

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

【问题讨论】:

    标签: xsd schema relaxng relaxng-compact


    【解决方案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" } }
    

    以 RelaxNG XML 语法表示:

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

    【讨论】:

    • 谢谢。每次都应该声明元素 p 吗?那么当我们考虑复杂的结构时,relaxNG会很长吗?还有其他选择吗?
    • 为了表达您在 RelaxNG 中需要的约束,除了声明多个 p 元素作为答案之外,我不知道其他选项。在 HTML5 github.com/validator/validator/tree/master/schema/html5 的 RelaxNG 模式中,我需要表达类似的约束,我使用了答案中描述的相同模式——也就是说,在语法中多次声明一个元素,每个元素都有不同的要求属性值。是的,我想它相对冗长,但与用 XML 表达相比,它至少在紧凑的语法中没有那么冗长。
    • 嗨 sideshowbaker,我尝试使用相同的 html5 表单 Nu 的 RNC,但我在 jing 中收到 dataLibrary 错误。是否可以使用此 RNC 并根据我的要求对其进行调整?
    • @Senthil 我想你想对你正在尝试的 RNC 提出一个单独的新问题,以及错误消息
    • OP 说“第 2 段应该在第 1 段之后”。然而,这里建议的模式允许&lt;p class="paragraph2"&gt; 成为body 中的第一个p 元素,因此前面没有标有paragraph1 类的元素。以 OP 的示例 XML 为例,删除第一个 p 元素,它将验证。在我看来,这不仅仅是 OP 试图正确的顺序,而且还有一个从 1 开始的连续序列。@Senthil 请加入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 2011-12-26
    • 2011-01-18
    • 1970-01-01
    • 2012-05-30
    • 2011-03-28
    相关资源
    最近更新 更多