Schematron / schematron-enhancement-proposals

This repository collects proposals to enhance Schematron beyond the ISO specification
9 stars 0 forks source link

Ability for role value to be dynamic or different per phase #64

Closed vincentml closed 8 months ago

vincentml commented 1 year ago

It would be useful to have a way for the role attribute value (on assert and report elements) be dynamically calculated or have different values based on the phase. The role attribute is often used to indicate a level such as "error", "warn", or "info" for validation rules. There are scenarios where an assert or report in a Schematron schema should produce an "error" role value with one phase and a "warn" role value with a different phase. Currently, an assert (or report) can be duplicated with different role attribute values, but I would rather not duplicate code if possible especially when the XPath test is complex.

This issue is related to a conversation in Slack https://xmlcom.slack.com/archives/C011NLXE4DU/p1686762296709629

rjelliffe commented 1 year ago

That is a good point.

One possibility might be to support xslt-style {} indicators. Which would make it part of the Query Language Binding, rather than Schematron itself: that might be OK.

Another possibility would be to piggyback on another proposal: the one that allows variables to be defined as part of phases, such as phase/let or phase/active/let. In this case, an @role could be a token or, if its value starts with a $, a variable reference. This has the advantage, if it is, of being more declarative and forcing things to have descriptive names.

< sch:assert role="$error-if-strict-testing" ...

Ricj

On Fri, 23 June 2023, 3:32 am vincentml, @.***> wrote:

It would be useful to have a way for the role attribute value (on assert and report elements) be dynamically calculated or have different values based on the phase. The role attribute is often used to indicate a level such as "error", "warn", or "info" for validation rules. There are scenarios where an assert or report in a Schematron schema should produce an "error" role value with one phase and a "warn" role value with a different phase. Currently, an assert (or report) can be duplicated with different role attribute values, but I would rather not duplicate code if possible especially when the XPath test is complex.

This issue is related to a conversation in Slack https://xmlcom.slack.com/archives/C011NLXE4DU/p1686762296709629

— Reply to this email directly, view it on GitHub https://github.com/Schematron/schematron-enhancement-proposals/issues/64, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF65KKPXGZRVUXSJPTE3UXDXMR6TLANCNFSM6AAAAAAZQQ3DNI . You are receiving this because you are subscribed to this thread.Message ID: @.***>

dmj commented 1 year ago

There are scenarios where an assert or report in a Schematron schema should produce an "error" role value with one phase and a "warn" role value with a different phase.

I read this as: There are scenarios where a failed assert or successful report is considered an error in one phase and a warning in a different phase.

If we read the use case this way then the promotion or demotion of a failed assert based on phase could be a function of the process that works with the SVRL report.

If we make the attribute value an expression that is evaluated during validation (via attribute value template {}), then you would need a way of introspection to know which phase is run. Relying on a variable bound in sch:phase (that's already possible!) would be an option.

AndrewSales commented 1 year ago

I like the proposal of using a phase variable for this, which is already supported, as @dmj says (phase/active/let is not, currently).

It would mean - correct me if I misunderstand the mechanics of what's proposed - that every phase whose active patterns have a constraint with a @role containing a variable reference would need to declare a variable with that name, since the variable is scoped to that phase (or risk a dynamic error).

By no means a blocker, but another rule worth adding to the Schematron for Schematron schemas, if we do go this route.

(It would also mean that you could no longer have a literal role value beginning with $, but that feels like an edge case.)

AndrewSales commented 1 year ago

FYI I have implemented this experimentally in XQS, see https://github.com/AndrewSales/XQS/tree/%2320.

So for a schema

<sch:schema>
  <sch:phase id='warn'>
    <sch:let name='dynamic-role' value='"warning"'/>
    <sch:active pattern='foo'/>
  </sch:phase>
  <sch:phase id='error'>
    <sch:let name='dynamic-role' value='"error"'/>
    <sch:active pattern='foo'/>
  </sch:phase>
  <sch:pattern id='foo'>
    <sch:rule context='*'>
      <sch:assert test='false()' role='$dynamic-role'></sch:assert>
    </sch:rule>
  </sch:pattern>
</sch:schema>

the role value reported differs depending on the phase selected, as per this passing test.

AndrewSales commented 8 months ago

This capability should probably also be extended to new attribute severity, re #58.

dmj commented 8 months ago

@vincentml You can use attribute value templates in SchXslt and SchXslt2. SchXslt2 will also provide the effective phase as value of the variable schxslt:phase during validation.

AndrewSales commented 8 months ago

This capability should probably also be extended to new attribute severity, re #58.

... and flag too.

AndrewSales commented 8 months ago

Latest working draft has, for flag, role and severity:

"If the value of a [flag] attribute given in a schema is a variable reference, its value shall be dynamically evaluated. This mechanism is provided to enable the [flag] value to vary, for example according to the selected phase and its in-scope variables."

I've also added the following to the XSLT n Annexes:

"Attribute value templates may be used to dynamically evaluate the value of attributes flag, role and severity."

rjelliffe commented 8 months ago

Given other proposals, should we be thinking about role="$dynamic-role-value" AND role="{$dynamic-role-value}" ?

So should it be that

Where the {} would only be available for QLB XSLT3.1, because it might be implemented by xslt's evaluate rather than by macro-substitution.

Security note: if adopted, the param value should not itself allow "{...}" to prevent compile-time code injections.

Regards Rick

On Mon, Mar 18, 2024 at 2:37 AM Andrew Sales @.***> wrote:

Latest working draft has, for flag, role and severity:

"If the value of a [flag] attribute given in a schema is a variable reference, its value shall be dynamically evaluated. This mechanism is provided to enable the [flag] value to vary, for example according to the selected phase and its in-scope variables."

I've also added the following to the XSLT n Annexes:

"Attribute value templates may be used to dynamically evaluate the value of attributes flag, role and severity."

— Reply to this email directly, view it on GitHub https://github.com/Schematron/schematron-enhancement-proposals/issues/64#issuecomment-2002512107, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF65KKLTUIEYOETA33DYM2LYYW2FHAVCNFSM6AAAAAAZQQ3DNKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMBSGUYTEMJQG4 . You are receiving this because you commented.Message ID: @.*** com>