Relaxng可以指定名称相同但属性不同的无序元素集吗? [英] Can relaxng specify an unordered set of elements with the same name, but different attributes?

查看:90
本文介绍了Relaxng可以指定名称相同但属性不同的无序元素集吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力自动化对采用XML并返回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>

链接对象是我要挂的位.问题出在这里:

  • 不能保证项目中元素的顺序,因此我试图将所有元素置于<interleave>结构中.
  • <item>中将有多个<link>元素,具有不同的属性集(即,<item>必须具有自我"链接,下载"链接和"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".我可以看到它的作用,但我希望它能够处理具有相同名称但属性不同的元素"作为唯一项的想法.

将链接引用移出交错即可对其进行解析,但是只要顺序改变了返回的数据,我都会等待验证器崩溃.

任何想法,还是不可能? 我正在处理的XML是否存在一个内在的问题,这将要求我将其中的一些问题移至测试应用程序中的更高处理逻辑(在运行更通用的XML验证后手动检查每种链接类型?)

解决方案

您似乎偶然发现了 Schematron 或RELAX NG和Schematron的组合中进行此操作. >

以下是使用Schematron版本检查您的<link>元素的代码段,该版本为由靖支持:

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

Im working to automate the testing of an API which takes and returns XML, so I want to translate the documented return data of the API into schema as much as possible. I chose RelaxNG for this task based on ease of use and learning.

Before I throw in all the info, here's the question:

Is it possible to describe "unordered set of elements, with the same name but different attributes" ?

Here is a sample object for what I'm having trouble describing:

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

The link objects are the bit that I'm getting hung up on. Here is the problem:

  • The order of elements inside item is not guaranteed, so I am trying to put all elements in <interleave> structure.
  • There will be multiple <link> elements inside <item>, with different sets of attributes (ie, <item> MUST have a 'self' link, a 'download' link, and a 'relatedData' link to be valid).
  • One of each link type is required, but again order is not guaranteed.

I tried to describe the schema like so:

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

the 'link' references are defined elsewhere like so:

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

The parser is not pleased about this - from jing I get error: the element "link" can occur in more than one operand of "interleave". I can see what its getting at but I hoped it could handle the idea of 'elements with the same name but different attributes' as unique items.

Moving the link refs out of interleave gets it to parse, but I'll be waiting for the validator to blow up whenever the order changes in the returned data.

Any ideas, or is this impossible? Is there an inherent issue with the XML I am processing that will require me to move some of this up to higher processing logic in my test application (manually check for each link type after running a more generic XML validation?)

解决方案

It looks like you have stumbled upon a restriction on interleave in RELAX NG. I would try to do this in Schematron, or perhaps a combination of RELAX NG and Schematron.

Here is a snippet that checks your <link> elements using the version of Schematron that is supported by Jing:

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

这篇关于Relaxng可以指定名称相同但属性不同的无序元素集吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆