Stylesheets icon indicating copy to clipboard operation
Stylesheets copied to clipboard

odd2odd.xsl sometimes fails to include some moduleSpec elements in the output

Open YvesMarcoux opened this issue 2 months ago • 5 comments

Say we have tiny.odd:

<schemaSpec ident="tiny" start="TEI" source="tei:current"> 
  <moduleRef key="tei"/>
  <moduleRef key="core"/>
</schemaSpec>

which we compile into a valid tiny_compiled.odd with odd2odd.xsl just fine.

If we now have tiny-prime.odd:

<schemaSpec ident="tiny-prime" start="TEI" source="tiny_compiled.odd"> 
  <moduleRef key="tei"/>
  <moduleRef key="core"/>
  <moduleRef key="textstructure" source="tei:current"/>
</schemaSpec>

odd2odd.xsl will compile it into an invalid ODD, which fails to include a <moduleSpec> element for textstructure.

For memory, this is what the <moduleSpec> for textstructure looks like in p5subset.xml:

<moduleSpec xml:id="DDS" ident="textstructure">
  <idno type="FPI">Default Text Structure</idno>
  <desc xml:lang="en" versionDate="2006-09-13">Default text structure</desc>
...
</moduleSpec>

I understand the prime goal of odd2odd.xsl is not to produce valid ODDs, but it's rather nice when it does.

Also, I wonder if this has an impact on the resulting schema (e.g. RNG) when odd2odd.xsl is chained with another, schema-producing, XSLT.

YvesMarcoux avatar Oct 22 '25 21:10 YvesMarcoux

I'm certain I have done this successfully in the past, e.g. putting back a module removed by the primary source schema by reaching back to the TEI schema. That ODD used a URL in the source pointing at the compiled ODD rather than the tei:current style URI. So possible that doesn't get correctly resolved if it's not on a schemaSpec element or that there's been a regression.

hcayless avatar Oct 23 '25 01:10 hcayless

The tei:current pointer is correctly resolved (@hcayless), but somehow, the moduleRefs that have their own source are ignored.

The following fix works at least for the cases I need to cover. Insert the following block:

      <xsl:for-each select="$top//tei:moduleRef[@source]">
        <xsl:variable name="orig" select="tei:workOutSource(.)"/>
        <xsl:variable name="key" select="normalize-space(@key)"/>
        <xsl:variable name="themodspec"
          select="document($orig)//tei:moduleSpec[normalize-space(@ident)=$key][1]"/>
        <xsl:copy select="$themodspec">
          <xsl:attribute name="n" select="ancestor::tei:div[last()]/@xml:id"/>
          <xsl:copy-of select="@*"/>
        </xsl:copy>
      </xsl:for-each>

just after https://github.com/TEIC/Stylesheets/blob/3a12490d9873ee9df7bf5c400a24417fc774848a/odds/odd2odd.xsl#L2234 Maybe someone could refine this into a permanent fix?

YvesMarcoux avatar Oct 23 '25 03:10 YvesMarcoux

But @YvesMarcoux , that code copies the <moduleSpec> element itself, no? A <moduleRef> is supposed to refer to those specification elements that declare themselves to be “in” the given module. I.e., something more along the lines of <xsl:copy-of select="document($orig)//*[@module eq $key]"/>.

sydb avatar Nov 10 '25 04:11 sydb

Yes, it does copy the <moduleSpec> itself, and that's the point. At the moment, the resulting ODD (let's call it tiny-prime_compiled.odd) has multiple @module="textstructure" attributes in it (one for each of the things in that module), but it fails to have a <moduleSpec> for that module. Hence, the schematron errors (33 of them) we get on tiny-prime_compiled.odd.

In contrast, tiny-prime_compiled.odd does have a <moduleSpec> for each of the two other modules included by way of a <moduleRef> that does not have a @source attribute (the higher-level @source of the <schemaSpec> being used in these cases).

I think the schematron errors make sense, because a compiled ODD should be self-sufficient, right? So it should have in itself a <moduleSpec> for each module it includes, no?

Anyway, my fix works fine (i.e., it results in an ODD that is valid [in particular, no schematron error] and corresponds to what we want) for the cases I need to handle at the moment. I am not suggesting it as a "true" fix because, not being an ODD specialist, I am worried it might not work properly in all possible cases.

YvesMarcoux avatar Nov 10 '25 21:11 YvesMarcoux

@sydb To add a bit more detail, here are the (pretty-printed) last lines of tiny-prime_compiled.odd without my fix:

       ...
        </elementSpec>
        <moduleSpec xmlns:rng="http://relaxng.org/ns/structure/1.0"
          xmlns:sch="http://purl.oclc.org/dsdl/schematron"
          xmlns:teix="http://www.tei-c.org/ns/Examples"
          xmlns:xi="http://www.w3.org/2001/XInclude" n="ST" xml:id="DSTTEI2" ident="tei"
          type="core"/>
        <moduleSpec xmlns:rng="http://relaxng.org/ns/structure/1.0"
          xmlns:sch="http://purl.oclc.org/dsdl/schematron"
          xmlns:teix="http://www.tei-c.org/ns/Examples"
          xmlns:xi="http://www.w3.org/2001/XInclude" n="CMC" ident="cmc"/>
        <moduleSpec xmlns:rng="http://relaxng.org/ns/structure/1.0"
          xmlns:sch="http://purl.oclc.org/dsdl/schematron"
          xmlns:teix="http://www.tei-c.org/ns/Examples" n="CO" xml:id="DCO" ident="core"/>
      </schemaSpec>
    </body>
  </text>
</TEI>

We see it has a moduleSpec for each of tei, cmc (I don't really know why), and core.

With my fix, a fourth moduleSpec is added, for textstructure:

        ...
        </elementSpec>
        <moduleSpec xmlns:rng="http://relaxng.org/ns/structure/1.0"
          xmlns:sch="http://purl.oclc.org/dsdl/schematron"
          xmlns:teix="http://www.tei-c.org/ns/Examples"
          xmlns:xi="http://www.w3.org/2001/XInclude" n="ST" xml:id="DSTTEI2" ident="tei"
          type="core"/>
        <moduleSpec xmlns:rng="http://relaxng.org/ns/structure/1.0"
          xmlns:sch="http://purl.oclc.org/dsdl/schematron"
          xmlns:teix="http://www.tei-c.org/ns/Examples"
          xmlns:xi="http://www.w3.org/2001/XInclude" n="CMC" ident="cmc"/>
        <moduleSpec xmlns:rng="http://relaxng.org/ns/structure/1.0"
          xmlns:sch="http://purl.oclc.org/dsdl/schematron"
          xmlns:teix="http://www.tei-c.org/ns/Examples" n="CO" xml:id="DCO" ident="core"/>
        <moduleSpec xmlns:rng="http://relaxng.org/ns/structure/1.0"
          xmlns:sch="http://purl.oclc.org/dsdl/schematron" n="DS" xml:id="DDS"
          ident="textstructure"/>
      </schemaSpec>
    </body>
  </text>
</TEI>

That's the only difference the fix makes. But it makes the ODD valid.

YvesMarcoux avatar Nov 11 '25 15:11 YvesMarcoux