Need a little recursion in RELAX NG external references

231 Views Asked by At

We've been using RELAX NG to specify and validate XML messages for our web-based API, and I was doing some housecleaning and started to make use of the <external> element.

In our schemas we have a <subscription> element, which has things like id and a period and so on, and also an <account>. This is pretty simple to spec in RELAX NG:

<?xml version="1.0"?>
<element name="subscription" xmlns="http://relaxng.org/ns/structure/1.0">
  <element name="id">
    <text />
  </element>

  <zeroOrMore>
    <externalRef href="./account.xml" />
  </zeroOrMore>
</element>

This schema would then be included by the actual message schema for a particular request.

The problem is that the <account> element can also have a number of <subscription> elements depending on the request (for example, sometimes we are searching for subscription data based on account information, and sometimes we would be searching for account information based on subscription data).

I tried:

<?xml version="1.0"?>
<element name="account" xmlns="http://relaxng.org/ns/structure/1.0">
  <element name="id">
    <text />
  </element>

  <zeroOrMore>
    <externalRef href="./subscription.xml" />
  </zeroOrMore>
</element>

But I got a (not unexpected) error when loading the schema: Detected an externalRef recursion

Is there a way to specify some kind of recursion limit - some way to know that my current <subscription> is a child of <account> and so should not have <account> children itself?

1

There are 1 best solutions below

0
On BEST ANSWER

As long as you point to the subscription element defined in you first Relax NG, the substruture has to match the pattern you are pointing to.

To achieve your goal, you should have another pattern definition for another subscription element with a different substructure.

Something like :

<define name="subscriptionDEF-2">
    <element name="subscription">
        <text/>
    </element>
</define>

And refer to if from your account element with a ref element.

<element name="account">
    <ref name="subscriptionDEF-2"/>
</element>