【问题标题】:Can relaxng specify an unordered set of elements with the same name, but different attributes?Relaxng 可以指定一组具有相同名称但属性不同的无序元素吗?
【发布时间】:2012-08-02 21:39:29
【问题描述】:

我正在努力自动化测试一个接受和返回 XML 的 API,所以我想尽可能地将 API 的记录返回数据转换为模式。基于易用性和学习性,我选择了 RelaxNG 来完成这项任务。

在我输入所有信息之前,这是一个问题:

是否可以描述“无序的元素集,同名但属性不同”?

这是一个我无法描述的示例对象:

<item>
    <id>d395136e-d060-4a6e-887c-c0337dd7ad09</id>
    <name>The item has a name</name>
    <link rel="self" type="type1" href="url" />
    <link rel="download" type="type2" href="url" />
    <link rel="relatedData" type="type3" href="url" />
</item>

链接对象是我要挂断的部分。问题来了:

  • item 中元素的顺序无法保证,所以我尝试将所有元素放入&lt;interleave&gt; 结构中。
  • &lt;item&gt; 内将有多个&lt;link&gt; 元素,具有不同的属性集(即&lt;item&gt; 必须有一个“self”链接、一个“下载”链接和一个“relatedData”链接才有效)。
  • 每种链接类型都需要一种,但不能保证同样的顺序。

我试图这样描述架构:

<element name="item">
    <interleave>
        <element name="id"><text/></element>
        <element name="name"><text/></element>
        <ref name="selfLink"/>
        <ref name="launchLink"/>
        <ref name="thumbnailLink"/>
    </interleave>
</element>

“链接”引用在其他地方定义如下:

 <define name="selfLink">
 <element name="link">
     <attribute name="href"><text/></attribute>
     <attribute name="rel"><value>self</value></attribute>
     <attribute name="type"><value>type1</value></attribute>
 </element>
 </define>

解析器对此并不满意 - 从 jing 我得到error: the element "link" can occur in more than one operand of "interleave"。我可以看到它的含义,但我希望它可以将“具有相同名称但属性不同的元素”的想法作为独特的项目来处理。

将链接 refs 移出 interleave 可以对其进行解析,但只要返回数据中的顺序发生变化,我就会等待验证器崩溃。

有什么想法,或者这不可能吗? 我正在处理的 XML 是否存在固有问题,需要我在测试应用程序中将其中的一些提升到更高的处理逻辑(在运行更通用的 XML 验证后手动检查每种链接类型?)

【问题讨论】:

  • 当你说“不同的属性”时,你真的是指“不同的属性值”吗?
  • 其实,是的,谢谢你的澄清。具有不同价值要求的同一组属性。

标签: xml relaxng


【解决方案1】:

您似乎在 RELAX NG 中偶然发现了 restriction on interleave。我会尝试在Schematron 中执行此操作,或者可能是 RELAX NG 和 Schematron 的组合。

这是一个 sn-p,它使用 supported by Jing 的 Schematron 版本检查您的 &lt;link&gt; 元素:

<schema xmlns="http://www.ascc.net/xml/schematron">
  <pattern name="link pattern">
    <rule context="item">
      <assert test='count(link) = 3'>There must be 3 link elements.</assert>
      <assert test="count(link[@rel = 'self' and @type ='type1']) = 1">There must be 1 link element wwhere @rel='self' and @type='type1'.</assert>
      <assert test="count(link[@rel = 'download' and @type ='type2']) = 1">There must be 1 link element where @rel='download' and @type='type2'.</assert>
      <assert test="count(link[@rel = 'relatedData' and @type = 'type3']) = 1">There must be 1 link element where @rel='relatedData' and @type='type3'.</assert>
    </rule>
  </pattern>
</schema>

【讨论】:

  • 这明白了,我能够为这个例子实现它并确认它有效。刚刚将我的脚趾浸入到将 schematron 嵌入到 RelaxNG 中,我认为这可能是目前的方法,直到/除非我找到一个障碍。我获得了将 xml 验证保存在一个地方(而不是在验证器和应用程序逻辑之间拆分)的能力,但需要设置更复杂的设置/处理管道。似乎是一个合理的权衡。
【解决方案2】:

查看以下架构是否有帮助

<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start>
    <element name="item">
        <interleave>
            <element name="id"><text/>
            </element>
            <element name="name"><text/></element>
            <oneOrMore>
                <ref name="link"/>
            </oneOrMore>
        </interleave>
    </element>
</start>

<define name="link">
    <element name="link">
        <attribute name="href"/>
        <choice>
            <group>
                <attribute name="rel"><value>self</value></attribute>
                <attribute name="type"><value>type1</value></attribute>
            </group>
            <group>
                <attribute name="rel"><value>download</value></attribute>
                <attribute name="type"><value>type2</value></attribute>
            </group>
            <group>
                <attribute name="rel"><value>relatedData</value></attribute>
                <attribute name="type"><value>type3</value></attribute>
            </group>
        </choice>
    </element>
</define>
</grammar>

【讨论】:

  • 虽然它不能让我对我的数据进行有保证的有效检查,但这个想法让我更接近 - 通过将 &lt;group&gt; 放在与 X links 的交错中,我可以匹配 'X链接可能在项目中某处分组的对象,并且通过在link 的架构中使用您的choice 想法,我可以验证找到的所有links 都来自一组有效的链接元素。更高级别的应用程序代码仍然需要检查接收到的 3 个链接是否是返回对象中预期的实际三个链接(“在item 中有一个下载链接、一个自我链接和一个相关数据链接”)。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
相关资源
最近更新 更多