如何在RELAX NG中建模`(A|B|C)*`(指定元素任意选择)内容模型?
解决RELAX NG标签汤内容模型的问题
你的原代码问题出在<zeroOrMore>的用法上:直接在<zeroOrMore>下放置多个<element>,RELAX NG会将其解析为「每次循环必须按顺序匹配A→B→C」,所以单独出现B时,第一个循环就匹配失败,自然通不过验证;而且这种写法还会允许重复出现A→B→C序列,完全不符合「不允许元素重复」的要求。
正确的RELAX NG模式写法
要实现每个标签可选(0或1次)、任意顺序出现、无重复的需求,用<interleave>配合<optional>就能简洁解决:
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> <!-- 其他定义 --> <define name="TagSoup"> <interleave> <optional><element name="A"><text /></element></optional> <optional><element name="B"><text /></element></optional> <optional><element name="C"><text /></element></optional> <!-- 继续添加更多标签的optional定义 --> </interleave> </define> </grammar>
写法说明
<interleave>:指定内部的子元素可以以任意顺序出现<optional>:让每个标签可以选择出现1次或完全不出现,天然避免了同一标签重复出现的情况- 这种写法简洁易扩展,完全匹配你的需求。
可选:要求至少一个标签出现
如果需要限制标签汤非空(至少有一个标签),可以在原有基础上增加非空校验:
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> <!-- 其他定义 --> <define name="TagSoup"> <group> <interleave> <optional><element name="A"><text /></element></optional> <optional><element name="B"><text /></element></optional> <optional><element name="C"><text /></element></optional> <!-- 其他标签 --> </interleave> <notAllowed><empty /></notAllowed> </group> </define> </grammar>
内容的提问来源于stack exchange,提问作者U. Windl
相关产品推荐
相关产品推荐

