Skip to content

Conversation

@raffazizzi
Copy link
Contributor

@raffazizzi raffazizzi commented Apr 13, 2024

This PR is work in progress to address issue #2369

  • Deprecate @generate on <classSpec> and implement a 6-month deprecation period.
  • Replace @expand on <classRef> in the 4 instances where it is mentioned in the Guidelines with <elementRef>s — done in commits 5a9b95e, 957c76a, and 98a1b95; note that some significant changes were made, e.g. deleting classes (that we had wanted for some reason)
  • Deprecate @expand on <classRef> for 6 months — oops; valid until date set to 2027-03-02 at the same time above was done
  • Deprecate @min and @max on <memberOf> for exactly the same period. (Class members must be in alternation, be in a sequence, or be interleaved. Having a member of a class occur in that class more than once does nothing if the class is in alternation, makes sense if the class is a sequence, and is not allowed if the class members are interleaved. We no longer allow class members to be in a sequence, so these attrs have no use.)
  • Add @org (moved into a class from <attList>) — What should class be named? Lots of work should be done on glosses & descriptions before we copy @org from <attList> to a class (used by <attList> and <classRef>). — tagdoc portion done; still work to do on prose, and could perhaps use an example or two
  • Add @cardinality attribute (see Deprecation of classSpec/@generate and classRef/@expand with alternative solutions. #2549 (comment)) — tagdoc portion done; still work to do on prose, and could perhaps use an example or two
  • Update Stylesheets to work with this new attribute combination
  • Adjust guidelines accordingly, see examples in Deprecation of classSpec/@generate and classRef/@expand with alternative solutions. #2549 (comment)
  • Make sure to explain in Guidelines how this works when <classRef> is a child of the forthcoming <interleave> element. See Add interleave element (and deprecate sequence/@preserveOrder)  #2538

@sydb
Copy link
Member

sydb commented Apr 20, 2024

Sorry, I am still not convinced that having <classRef> as a child of <alternate> or <interleave> will be sufficient. So bear with me while I think this through aloud.

We are talking about references to classes that are currently expandable into one of:

  • "alternation" (( a | b | c ), the default),
  • "sequence" (( a, b, c )),
  • "sequenceOptional" (( a?, b?, c? )),
  • "sequenceRepeatable" (( a+, b+, c+)), and
  • "sequenceOptionalRepeatable" (( a*, b*, c* )).

We are planning to drop the "sequence*" possibilities because we have no mechanism of determining a good sequence or allowing a customizer to change it. But we are (or at least I am) hoping to add interleave capability. In which case we need to be able to represent the parallel structures: "interleave" (( a & b & c )), "interleaveOptional" (( a? & b? & c? )), "interleaveRepeatable" (( a+ & b+ & c+)), and "interleaveOptionalRepeatable" (( a* & b* & c* )).

I don’t think there is any way to represent those 4 possibilities just by noticing that the parent of <classRef> is <interleave>. Besides, what if I wanted an interleave of the classes, not of the elements that are members the classes? E.g., we would like the content model of <respStmt> to be

  <interleave>
    <elementRef key="resp" minOccurs="1" maxOccurs="unbounded"/>
    <classRef key="model.nameLike.agent" minOccurs="1" maxOccurs="unbounded"/>
  </interleave>

(We can’t do that, of course, because we can’t use <interleave>, as it has no equivalent in the DTD language.) That is, we want a minimum of <resp> and one of the nameLike.agent elements, not all of them.

So I think I have now convinced myself that being a child of <interleave> does not cut it. We need a tighter mechanism to specify the expansion of a class reference. (By “tighter” I mean tied closer to the class reference itself.)

@raffazizzi
Copy link
Contributor Author

raffazizzi commented Apr 29, 2024

Would it suffice to add an attribute to <interleave> to indicate the type of interleaving desired?

@raffazizzi raffazizzi self-assigned this Apr 29, 2024
@martindholmes
Copy link
Contributor

We could add an attribute to classRef:

@use="members", @use="class", or

@use="one", @use="any", or @use="all"

@tuurma
Copy link
Contributor

tuurma commented Nov 13, 2024

F2F in BA: Action on SB, JT, and RV to meet post-F2F to formalize a proposal, taking into account also #2538

@raffazizzi
Copy link
Contributor Author

raffazizzi commented Dec 3, 2024

Subgroup @sydb , @joeytakeda , @raffazizzi suggest using @org (same as the one on <attList> — value of either choice or group) to indicate how the members of a class should be organized, which will result in either <rng:alternate> or <rng:interleave>, respectively.

Introduce a new attribute potentially called @membersOccur that indicate the cardinality of each member of the class, such as single, repeatable (oneOrMore or +), optional (?), optionalRepeatable (zeroOrMore or *).

(Defaults in bold.)

EDIT: F2F in Kraków decides "membersOccur" should be "cardinality" with values "one", "oneOrMore", "zeroOrOne", "zeroOrMore"

@sydb
Copy link
Member

sydb commented Dec 3, 2024

Examples to clarify @raffazizzi’s summary, above …

Imagine that we have 3 classes, model.firstThree, model.midThree, and model.lastThree. The members of model.firstThree are <a>, <b>, and <c>; the members of model.midThree are <m>, <n>, and <ñ>; and the members of model.lastThree are <x>, <y>, and <z>. (Yes, I am using the Spanish alphabet because it has an odd number of letters.) Furthermore we have a 4th class, model.randFour whose members are <a>, <d>, <n>, and <r>.

We are suggesting the following. (Note that we did not discuss the pattern names at all, but they are essentially arbitrary, as they only occur in the RELAXNG schema, the user never sees them. So the names should be chosen to make debugging easier.)

class definitions

Each class gets expanded to 8 spearate patterns in the RELAX NG output. Here is what model.firstThree would look like in the compact syntax. (Remember that we are planning to get rid of classSpec/@generate, so all 8 are generated for every class, the ODD writer has no way to say “only repeatable_alternated should be usable”.)

model.firstThree_singles_interleaved            =  a  & b  & c
model.firstThree_singles_alternated             =  a  | b  | c
model.firstThree_optional_interleaved           =  a? & b? & c?
model.firstThree_optional_alternated            =  a? | b? | c?
model.firstThree_repeatable_interleaved         =  a+ & b+ & c+
model.firstThree_repeatable_alternated          =  a+ | b+ | c+
model.firstThree_optionalRepeatable_interleaved =  a* & b* & c*
model.firstThree_optionalRepeatable_alternated  =  a* | b* | c*

(For the masochists among you who prefer to see this in the XML syntax you can find it near the bottom of this comment.)

The same sort of 8 separate definitions holds for model.midThree (with "m", "n", & "ñ"), model.lastThree (with "x", "y", & "z"), and model.randFour (with "a", "d", "n", & "r"). If you want to play around with a schema that has these classes already defined, you are in luck. I have created a shell of a schema for that very purpose. Note the ".txt" extension (which is there just so gitHub will let me put it here) should probably be removed.

example one

Either of these:

<classRef key="model.firstThree"/>
<classRef key="model.firstThree" org="group" membersOccur="single"/>

would resolve to

<rng:ref name="model.firstThree_singles_interleaved"/>

example two

<classRef key="model.midThree" org="choice" membersOccur="single"/>

would resolve to

<rng:ref name="model.midThree_singles_alternated"/>

example three

<classRef key="model.lastThree" org="choice" membersOccur="optional"/>

would resolve to

<rng:ref name="model.lastThree_optionals_alternated"/>

example four

<classRef key="model.firstThree" org="group" membersOccur="repeatable" minOccurs="2" maxOccurs="3"/>

would resolve to

<rng:group>
  <rng:ref name="model.firstThree_repeatable_interleaved"/>
  <rng:ref name="model.firstThree_repeatable_interleaved"/>
  <rng:optional>
    <rng:ref name="model.firstThree_repeatable_interleaved"/>
  </rng:optional>
</rng:group>

example five

<alternate>
  <classRef key="model.firstThree" org="group" membersOccur="optionalRepeatable"/>
  <classRef key="model.midThree"   org="group" membersOccur="optionalRepeatable"/>
  <classRef key="model.lastThree"  org="group" membersOccur="optionalRepeatable"/>
</alternate>

would resolve to

<rng:choice>
  <rng:ref name="model.firstThree_optionalRepeatable_interleaved"/>
  <rng:ref name="model.midThree_optionalRepeatable_interleaved"/>
  <rng:ref name="model.lastThree_optionalRepeatable_interleaved"/>
</rng:choice>

which itself has the same effect as the following (in the compact syntax):

(
  ( a* & b* & c* )
  |
  ( m* & n* & ñ* )
  |
  ( x* & y* & z* )
)

That is,
any combination of any number of <a>, <b>, and <c> (including none of them), or
any combination of any number of <m>, <n>, and <ñ> (including none of them), or
any combination of any number of <x>, <y>, and <z> (including none of them).

So

 <a/><a/><b/><b/><b/>

would be valid, but

 <a/><y/>

would not be valid.

example six

<interleave>
  <classRef key="model.firstThree" org="choice" membersOccur="repeatable"/>
  <classRef key="model.midThree"   org="choice" membersOccur="repeatable"/>
  <classRef key="model.lastThree"  org="choice" membersOccur="repeatable"/>
</interleave>

would resolve to

<rng:interleave>
  <rng:ref name="model.firstThree_repeatable_alternated"/>
  <rng:ref name="model.midThree_repeatable_alternated"/>
  <rng:ref name="model.lastThree_repeatable_alternated"/>
</rng:interleave>

which itself has the same effect as the following (in the compact syntax):

(
  ( a+ | b+ | c+ )
  &
  ( m+ | n+ | ñ+ )
  &
  ( x+ | y+ | z+ )
)

That is a weird content model that forces the user to pick one element from each “set” (e.g., <a>, <n>, and <z>), but once chosen, each of those three elements may occur one or more times in any order.

So

    <a/><n/><z/><z/><n/><a/>

would be valid, but

    <a/><n/><z/><z/><n/><c/>

would not be valid (because it has both an <a> and a <c>, which are both from the same “set”).

example seven

<interleave minOccurs="1" maxOccurs="unbounded">
  <classRef key="model.firstThree"/>
  <classRef key="model.lastThree"/>
</interleave>

would resolve to

<rng:oneOrMore>
  <rng:interleave>
    <rng:ref name="model.firstThree_singles_alternated"/>
    <rng:ref name="model.lastThree_singles_alternated"/>
  </rng:interleave>
</rng:oneOrMore>

which itself has the same effect as the following (in the compact syntax):

(
  ( a | b | c )
  &
  ( x | y | z )
)+

example eight

This example is just like example six but uses model.randFour instead of model.lastThree, which results in an INVALID RELAX NG schema.

<interleave>
  <classRef key="model.firstThree" org="choice" membersOccur="repeatable"/>
  <classRef key="model.midThree"   org="choice" membersOccur="repeatable"/>
  <classRef key="model.randFour"   org="choice" membersOccur="repeatable"/>
</interleave>

would resolve to

<rng:interleave>
  <rng:ref name="model.firstThree_repeatable_alternated"/>
  <rng:ref name="model.midThree_repeatable_alternated"/>
  <rng:ref name="model.randFour_repeatable_alternated"/>
</rng:interleave>

which itself has the same effect as the following (in the XML syntax with line numbers added):

01)  <rng:interleave>
02)    <rng:choice>
03)      <rng:oneOrMore>
04)        <rng:ref name="a"/>
05)      </rng:oneOrMore>
06)      <rng:oneOrMore>
07)        <rng:ref name="b"/>
08)      </rng:oneOrMore>
09)      <rng:oneOrMore>
10)        <rng:ref name="c"/>
11)      </rng:oneOrMore>
12)    </rng:choice>
13)    <rng:choice>
14)      <rng:oneOrMore>
15)        <rng:ref name="m"/>
16)      </rng:oneOrMore>
17)      <rng:oneOrMore>
18)        <rng:ref name="n"/>
19)      </rng:oneOrMore>
20)      <rng:oneOrMore>
21)        <rng:ref name="ñ"/>
22)      </rng:oneOrMore>
23)    </rng:choice>
24)    <rng:choice>
25)      <rng:oneOrMore>
26)        <rng:ref name="r"/>
27)      </rng:oneOrMore>
28)      <rng:oneOrMore>
29)        <rng:ref name="a"/>
30)      </rng:oneOrMore>
31)      <rng:oneOrMore>
32)        <rng:ref name="n"/>
33)      </rng:oneOrMore>
34)      <rng:oneOrMore>
35)        <rng:ref name="d"/>
36)      </rng:oneOrMore>
37)    </rng:choice>
38)  </rng:interleave>

which is illegal both because

  1. //rng:interleave//rng:ref[@name='a'] occurs twice (lines 04 & 29), and
  2. //rng:interleave//rng:ref[@name='n'] occurs twice (lines 18 & 32).

To my surprise, jing reports the error for "n", not for "a". Not that it matters. (I had expected it to report "a" because it occurs first. Oh well.)

In any case, Stylesheets issue #719 is for figuring out what to do with invalid RELAX NG.

bonus:
sample definition of model.firstThree in XML syntax

  <rng:define name="model.firstThree_singles_interleaved">
    <rng:interleave>
      <rng:ref name="a"/>
      <rng:ref name="b"/>
      <rng:ref name="c"/>
    </rng:interleave>
  </rng:define>
  <rng:define name="model.firstThree_singles_alternated">
    <rng:choice>
      <rng:ref name="a"/>
      <rng:ref name="b"/>
      <rng:ref name="c"/>
    </rng:choice>
  </rng:define>
  <rng:define name="model.firstThree_optional_interleaved">
    <rng:interleave>
      <rng:optional>
        <rng:ref name="a"/>
      </rng:optional>
      <rng:optional>
        <rng:ref name="b"/>
      </rng:optional>
      <rng:optional>
        <rng:ref name="c"/>
      </rng:optional>
    </rng:interleave>
  </rng:define>
  <rng:define name="model.firstThree_optional_alternated">
    <rng:choice>
      <rng:optional>
        <rng:ref name="a"/>
      </rng:optional>
      <rng:optional>
        <rng:ref name="b"/>
      </rng:optional>
      <rng:optional>
        <rng:ref name="c"/>
      </rng:optional>
    </rng:choice>
  </rng:define>
  <rng:define name="model.firstThree_repeatable_interleaved">
    <rng:interleave>
      <rng:oneOrMore>
        <rng:ref name="a"/>
      </rng:oneOrMore>
      <rng:oneOrMore>
        <rng:ref name="b"/>
      </rng:oneOrMore>
      <rng:oneOrMore>
        <rng:ref name="c"/>
      </rng:oneOrMore>
    </rng:interleave>
  </rng:define>
  <rng:define name="model.firstThree_repeatable_alternated">
    <rng:choice>
      <rng:oneOrMore>
        <rng:ref name="a"/>
      </rng:oneOrMore>
      <rng:oneOrMore>
        <rng:ref name="b"/>
      </rng:oneOrMore>
      <rng:oneOrMore>
        <rng:ref name="c"/>
      </rng:oneOrMore>
    </rng:choice>
  </rng:define>
  <rng:define name="model.firstThree_optionalRepeatable_interleaved">
    <rng:interleave>
      <rng:zeroOrMore>
        <rng:ref name="a"/>
      </rng:zeroOrMore>
      <rng:zeroOrMore>
        <rng:ref name="b"/>
      </rng:zeroOrMore>
      <rng:zeroOrMore>
        <rng:ref name="c"/>
      </rng:zeroOrMore>
    </rng:interleave>
  </rng:define>
  <rng:define name="model.firstThree_optionalRepeatable_alternated">
    <rng:choice>
      <rng:zeroOrMore>
        <rng:ref name="a"/>
      </rng:zeroOrMore>
      <rng:zeroOrMore>
        <rng:ref name="b"/>
      </rng:zeroOrMore>
      <rng:zeroOrMore>
        <rng:ref name="c"/>
      </rng:zeroOrMore>
    </rng:choice>
  </rng:define>

sydb added 12 commits September 2, 2025 23:15
of a class reference of "sequence" just list the element references in
the right order. This is being done in preparation for removing the
expand= attribute.
of a class reference of "sequenceOptional" just list the element
references in the right order with a minOccurs= of 0. This is being
done in preparation for removing the expand= attribute.
in the specifications of msIdentifier and altIdentifier with just a list
the element references in the right order with a minOccurs= of 0. This is
being done in preparation for removing the expand= attribute.
element that we probably will not use — it has require= instead of
org=.
classRef element with org= (and membersOccur=) attributes
use of org= and membersOccur= to when the class reference is
in a content model.
schema & tagdoc portion of attr changes to classRef. (Still need to work
on the prose.) Not thoroughly tested. Note that we are not all that
happy with this setup — we would have preffered to have a generic
version of att.organizable, and have both attList and classRef over-
ride the value list and defaut values (and maybe other things, too),
but found that the Stylesheets don’t seem to support that: if all
elements that are member of the class override the attribute def,
the class was getting dropped.
I had used incorrect glosses for vallues of cardinality=
of them v. important (an extraneous “not” :-)
the memberOf element, as they make no sense except when used in a
sequence reference, which has been deprecated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants