From bd8ceb5c3b2fefd6ef53196869eadb404eae1f83 Mon Sep 17 00:00:00 2001 From: "C. M. Sperberg-McQueen" Date: Wed, 1 May 2024 11:50:22 -0600 Subject: [PATCH 1/2] Extensive cosmetic changes to test catalog RNC schema Re-indentation, addition of ## comments (to turn into documentation elements in the RNG form of the schema), introduction of 'div' elements to mark groupings. --- schemas/test-catalog.rnc | 1207 ++++++++++++++++++++++---------------- 1 file changed, 692 insertions(+), 515 deletions(-) diff --git a/schemas/test-catalog.rnc b/schemas/test-catalog.rnc index bcbc7b4c..aa19b515 100644 --- a/schemas/test-catalog.rnc +++ b/schemas/test-catalog.rnc @@ -3,520 +3,697 @@ namespace unqualified = "" grammar { - # RNC grammar for test catalog. - # - # Revisions: - # 2023-03-13 : CMSMcQ : Add metadata for dependencies (and correct typos) - # 2022-05-31 : CMSMcQ : Make 'error' attribute obligatory, - # add 'wrong-error' as result. - # 2022-04-12 : CMSMcQ : Move base version of this to ixml repo - # 2022-04-11 : CMSMcQ : Add dynamic-error as expected result - # 2022-02-14 : CMSMcQ : Move metadata from attributes to elements - # 2022-02-06 : CMSMcQ : Add a quick and dirty report format. - # 2021-12-22 : CMSMcQ : Make 'created' optional on individual tests; - # notionally, let it be inherited from test set. - # 2021-11-11 : CMSMcQ : Revamp result to allow multiple results - # and include assert-not-a-grammar. - # Rewrite some comments. - # 2021-10-31 : CMSMcQ : Commit some changes: @name on test-case, - # allow at most one grammar for each test - # set (grammars may be inherited from ancestor - # test sets). - # 2021-01-25 : CMSMcQ : Sketch this out by hand. - # - # To do: - # - rewrite test-set to allow test cases only if a grammar is - # specified on the test-set or some ancestor. - # - allow description to be (p+ | xhtml:div+) HTML - # - supply types for tokenized attributes? - # - -# Notational convention: definitions starting in uppercase (e.g. -# Metadata, Grammar-spec) are for content-model expressions. -# Definitions starting in lowercase (e.g. test-catalog) are for -# individual elements, usually with the same name as the element. -# -# (Exception: element test-set has two definitions, test-set-0 -# and test-set-1.) - -# The normal starting points are test-catalog and test-report. -# But to allow individual test sets and tests to be reported -# separately, we also allow lower-level result elements as the -# start symbol. - - start = test-catalog | test-report - | test-set-results | grammar-result | test-result - -# test-catalog, test-report - - # A test catalog is a collection of test sets, with common - # metadata. - test-catalog = element test-catalog { - attribute name { text }, - attribute release-date { xsd:date }, - external-atts, - (Metadata - & - (test-set-0 | test-set-ref)*) - } - - # A test report is a collection of test set reports, with common - # metadata. - test-report = element test-report { - element metadata { - (element name { text }, - element report-date { xsd:date | xsd:dateTime }, - element processor { text }, - element processor-version { text }?, - element catalog-uri { text }, - element catalog-date { text }?) - & - Metadata - }, - external-atts, - (Metadata - & - test-set-results*) - } - -# Metadata - - # At various levels we allow metadata: prose descriptions, - # pointers to external documentation, or arbitrary XML - # elements ('application-specific information'), and - # miscellaneous technical details about dependencies of a test - # (or, usually, of the test result) and for a test result the - # environment within which a test was run. - - Metadata = (description | app-info | doc | dependencies)* - - # The 'description' element contains a prose description. - # Say what you think needs saying. - description = element description { - external-atts, - p* - } - - # The 'doc' element carries an 'href' attribute pointing to - # relevant external documentation. - doc = element doc { - external-atts, - attribute href { xsd:anyURI } - } - - # The 'app-info' is an escape hatch which can contain any XML - # at all. It can be used for processor-specific information. - # (Please document what you do!) - app-info = element app-info { - external-atts, - any-element* - } - - # The 'options' element (in the test-catalog namespace, but - # allowed only within app-info) is used to mark results which - # depend (for a given processor) on the options with which the - # processor was invoked. Options are assumed describable with - # name/value pairs encoded as namespace-qualified attributes. - # Typically the attribute name names the option, and the value - # says how to set it. Examples and some discussion are in - # ../tests/grammar-misc/test-catalog.xml - - # If all the option/setting pairs on any options element in - # the app-info element apply, then any of the results - # specified in that app-info element is acceptable. - - # So: for both the options elements and the results in the - # app-info there is an implicit disjunction: if any of the - # options elements applies, then any of the results is OK. - # For the various name/value pairs on an options element, - # there is an implicit conjunction: the options element - # applies if ALL of the name/value pairs apply. - - # N.B. The options element, and the method of handling options - # it represents, is to be regarded as experimental. - - options = element options { - external-atts, - empty - } - - # The environment element works much the same way as the - # options element; when results reported for a test depend on - # the environment (e.g. which version of Java is used, or - # which browser an in-browser processor uses, or ...), then - # the relevant information should be given on an 'environment' - # element wrapped in an 'app-info' element at the appropriate - # level of the test results. (Top level if applicable to all, - # test set if applicable only to that test set, test result if - # applicable to that result.) - - # The difference between options and environment is that - # options are assumed to be settable at parse time by whoever - # calls the ixml processor, and the environment is less likely - # to be settable that way. In case of gray areas, explain - # your usage in the test catalog. - - environment = element environment { - external-atts, - empty - } - - # The difference between options and environment is that - # options are assumed to be settable at parse time by whoever - # calls the ixml processor, and the environment is less likely - # to be settable that way. In case of gray areas, explain - # your usage in the test catalog. - - # The 'dependencies' element identifies conditions that must - # hold for the results given for a test to hold. Like - # 'options' and 'environment', it allows an arbitrary set of - # name/value pairs (namespace-qualified attributes). If all - # of them apply, the test result given is applicable. - - # Some dependencies are standardized: any processor must - # conform to some version of Unicode but we don't specify which, - # so the processor must specify. Test results must be labeled - # with the appropriate Unicode version(s). - - dependencies = element dependencies { - attribute Unicode-version { text }, - external-atts, - empty - } - - # The differences are: - # options - implementation-defined, typically settable by caller - # at parse time. Wrap in app-info to label results - # (often non-standard) which depend on how the - # processor was invoked. - # environment - relevant but not under implementation control. - # Wrap in app-info, use to label results which depend - # on the environment within which the processor is - # running (or within which a test result was obtained). - # dependencies - used to label test cases whose results - # depend on which version of another spec is applicable. - -# test-set, test-set-results - - # A test set is a collection of tests (or possibly subordinate - # test sets, or both) with common metadata and a common - # grammar. - - # Test cases are allowed only after a grammar is specified. - - # We keep track of whether an ancestor has specified a grammar - # by having two nonterminals for test sets: test-set-0 is used - # when no ancestor has specified a grammar, test-set-1 when - # at least one grammar has been specified. - - # If no ancestor has specified a grammar, test cases are allowed - # in this test set only if this test set does specify a grammar. - # Use test-set-0 or -1 to pass the news along. - - test-set-0 = element test-set { - attribute name { text }, - external-atts, - (Metadata - & - (History, - ( (test-set-0 | test-set-ref)* - | (Grammar-spec, (test-set-1 | test-set-ref | test-case)*) ))) - } - - # If an ancestor has specified a grammar, test cases are allowed - # in this test set even if there is no grammar at this level. - - test-set-1 = element test-set { - attribute name { text }, - external-atts, - (Metadata - & - (History, - Grammar-spec?, - (test-set-1 | test-set-ref | test-case)*)) - } - - test-set-results = element test-set-results { - attribute name { text }, - external-atts, - (Metadata - & - (Grammar-results?, - (test-set-results | test-result)*)) - } - - # Grammars can be in invisible XML or in visible XML. - # They can be inline or external. They can be marked - # as a grammar test or not. - - Grammar-data = (ixml-grammar - | vxml-grammar - | ixml-grammar-ref - | vxml-grammar-ref) - - Grammar-spec = (Grammar-data, grammar-test?) - - # In the results file, we may omit the grammar, or include - # it, possibly both reproducing the reference and giving - # the grammar inline. - Grammar-results = (Grammar-data*, grammar-result*) - - # Q. Why is the grammar optional? - # A. Because in a nested test set we may want to inherit the - # grammar from the parent test set. In a top-level test - # set with no direct test-case children, we may just be - # pointing to multiple test sets which each provide their - # own grammar. By the time we reach a test case we must - # have at least one grammar, but we don't need on at every - # level. - # Q. Why can't there be multiple grammars? - # A. First, it's error prone: it would work only if all of them - # were guaranteed equivalent. We don't want to have to check - # that, and we don't want the mess that will result if it - # turns out not to be true. Second, it complicates reporting - # unnecessarily. It's simpler when one test case is one - # grammar + input + result triple. - - test-set-ref = element test-set-ref { - external-atts, - attribute href { xsd:anyURI } - } - - # ixml-grammar: grammar in invisible-XML form - ixml-grammar = element ixml-grammar { - external-atts, - text - } - - ixml-grammar-ref = element ixml-grammar-ref { - external-atts, - attribute href { xsd:anyURI } - } - - # vxml-grammar: grammar in visible-XML form (either a parsed - # ixml grammar, translated into XML, or something created in - # XML) - # - # N.B. It is tempting to embed a schema for ixml grammars here - # to enforce the correct XML form. But we do not require a - # legal ixml grammar, because it may be a negative test case. - - vxml-grammar = element vxml-grammar { - external-atts, - any-element - } - - vxml-grammar-ref = element vxml-grammar-ref { - external-atts, - attribute href { xsd:anyURI } - } - - # grammar-test: signals that this grammar should be checked - # and either accepted or declined as a grammar. - - grammar-test = element grammar-test { - external-atts, - (Metadata & (History?, result)) - } - - grammar-result = element grammar-result { - attribute result { result-type }, - external-atts, - (Metadata & (result-report?)) - } - - -# test-case - - # test-case: describes one test case, with metadata, history, - # and expected result. - - test-case = element test-case { - attribute name { text }, - external-atts, - (Metadata & (History?, Test-string, result)) - } - - test-result = element test-result { - attribute name { text }, - attribute result { result-type }, - external-atts, - (Metadata & - (Grammar-data*, (Test-string)*, result-report?) - ) - } - - result-type = 'pass' # results are as expected - | 'fail' # results not as expected - | 'wrong-error' # right overall result, wrong error code - | 'wrong-state' # right overall result, wrong ixml:state value(s) - | 'not-run' - | 'other' - - # Test-string: in-line or external - - Test-string = (test-string | test-string-ref) - - test-string = element test-string { - external-atts, - text - } - - test-string-ref = element test-string-ref { - external-atts, - attribute href { xsd:anyURI } - } - -# result - - # result: specifies the expected result of a test; - # contains an assertion of some kind. - result = element result { - external-atts, - Assertion - } - - result-report = element result { - external-atts, - Assertion?, - Observation? - } - - -# Test assertions - - # Several kinds of result are possible. - # - # - In the common case we will have one expected XML result. We - # specify it with assert-xml or assert-xml-ref (inline or - # external). - # - # - For ambiguous sentences, we may and should specify several - # XML results, any of which is acceptable. So the XML - # assertions can repeat, with an implicit OR as their meaning. - # - # - In the case of infinite ambiguity, we can and should specify - # a finite subset of the expected results, which we add to as - # needed. - # - # - If the input is not be a sentence in the language defined - # by the grammar, we use assert-not-a-sentence. - # - # - If the grammar specified is not a conforming ixml grammar, - # then we use assert-not-a-grammar. - # - # - If the particular grammar + input pair would produce - # ill-formed output if the normal rules were followed, then - # we use assert-dynamic-error. - # - # Logically speaking, in the case of a grammar-test, there is no - # useful distinction between assert-not-a-sentence and - # assert-not-a-grammar. Casuists can argue over which makes - # more sense, but in practice they should be treated as - # equivalent. They are usefully different only for normal - # test cases. - # - # Since dynamic errors are allowed to be caught statically, - # some processors may return assert-not-a-grammar when the test - # catalog expects assert-dynamic-error. - # - # Errors in the grammar and dynamic errors may be associated - # with error codes. These are now required. - - Assertion = ((assert-xml-ref | assert-xml)+ - | assert-not-a-sentence - | assert-not-a-grammar - | assert-dynamic-error) - - Error-Code = attribute error-code { text } - - assert-xml-ref = element assert-xml-ref { - external-atts, - attribute href { xsd:anyURI } - } - assert-xml = element assert-xml { - external-atts, - any-element+ - } - assert-not-a-sentence = element assert-not-a-sentence { - external-atts, - Metadata - } - assert-not-a-grammar = element assert-not-a-grammar { - Error-Code, - external-atts, - Metadata - } - assert-dynamic-error = element assert-dynamic-error { - Error-Code, - external-atts, - Metadata - } - - Observation = ((reported-xml-ref | reported-xml)+ - | reported-not-a-sentence - | reported-not-a-grammar - | reported-dynamic-error) + # RNC grammar for test catalog. + # + # Revisions: + # 2024-05-01 : CMSMcQ : re-indent, use div for grouping, add + # double-hash comments for elements and + # important patterns + # 2023-03-13 : CMSMcQ : Add metadata for dependencies (and + # correct typos) + # 2022-05-31 : CMSMcQ : Make 'error' attribute obligatory, + # add 'wrong-error' as result. + # 2022-04-12 : CMSMcQ : Move base version of this to ixml + # repo + # 2022-04-11 : CMSMcQ : Add dynamic-error as expected result + # 2022-02-14 : CMSMcQ : Move metadata from attributes to + # elements + # 2022-02-06 : CMSMcQ : Add a quick and dirty report format. + # 2021-12-22 : CMSMcQ : Make 'created' optional on individual + # tests; notionally, let it be + # inherited from test set. + # 2021-11-11 : CMSMcQ : Revamp result to allow multiple + # results and include + # assert-not-a-grammar. Rewrite some + # comments. + # 2021-10-31 : CMSMcQ : Commit some changes: @name on + # test-case, allow at most one grammar + # for each test set (grammars may be + # inherited from ancestor test sets). + # 2021-01-25 : CMSMcQ : Sketch this out by hand. + # + # To do: + # - allow description to be (p+ | xhtml:div+) HTML + # - supply types for tokenized attributes? + # + + # Notational convention: definitions starting in uppercase + # (e.g. Metadata, Grammar-spec) are for content-model + # expressions. Definitions starting in lowercase + # (e.g. test-catalog) are for individual elements, usually + # with the same name as the element. + # + # (Exception: element test-set has two definitions, + # test-set-0 and test-set-1.) + + # The normal starting points are test-catalog and + # test-report. But to allow individual test sets and tests + # to be reported separately, we also allow lower-level result + # elements as the start symbol: test-set-results, + # grammar-rule, test-result. + + start = test-catalog | test-report + | test-set-results | grammar-result | test-result + + div { + + # test-catalog, test-report + + ## test-catalog: A test catalog is a collection of test + ## sets, with common metadata. + test-catalog = element test-catalog { + attribute name { text }, + attribute release-date { xsd:date }, + external-atts, + (Metadata + & + (test-set-0 | test-set-ref)*) + } + + ## test-report: A test report is a collection of test set + ## reports, with common metadata. + test-report = element test-report { + element metadata { + (element name { text }, + element report-date { + xsd:date | xsd:dateTime + }, + element processor { text }, + element processor-version { text }?, + element catalog-uri { text }, + element catalog-date { text }?) + & + Metadata + }, + external-atts, + (Metadata + & + test-set-results*) + } + } + div { + + # Metadata + + # At various levels we allow metadata: prose descriptions, + # pointers to external documentation, or arbitrary XML + # elements ('application-specific information'), and + # miscellaneous technical details about dependencies of a + # test (or, usually, of the test result) and for a test + # result the environment within which a test was run. + + ## Metadata: descriptions, documentation, dependencies, + ## or application-specific information + Metadata = (description | app-info | doc | dependencies)* + + ## description: a prose description of the item. + ## Say what you think needs saying. + description = element description { + external-atts, + p* + } + + ## doc: pointer to documentation relevant to the item. + ## The 'href' attribute gives the URI. + doc = element doc { + external-atts, + attribute href { xsd:anyURI } + } + + ## app-info: The 'app-info' element is an escape hatch which + ## can contain any XML at all. It can be used for + ## processor-specific information. (Please document what you + ## do!) + app-info = element app-info { + external-atts, + any-element* + } + + ## options: The 'options' element is embedded within app-info + ## to mark results which depend (for a given processor) on + ## the options with which the processor was invoked. + options = element options { + external-atts, + empty + + # N.B. The 'options' element is in the + # test-catalog namespace, but it is allowed + # only within app-info. + + # Options are assumed describable with + # name/value pairs encoded as + # namespace-qualified attributes. Typically + # the attribute name names the option, and the + # value says how to set it. + + # Examples and some discussion are in + # ../tests/grammar-misc/test-catalog.xml + + # If all the option/setting pairs on any + # options element in the app-info element + # apply, then any of the results specified in + # that app-info element is acceptable. + + # So: for both the options elements and the + # results in the app-info there is an implicit + # disjunction: if any of the options elements + # applies, then any of the results is OK. For + # the various name/value pairs on an options + # element, there is an implicit conjunction: + # the options element applies if ALL of the + # name/value pairs apply. + + # N.B. The options element, and the method of + # handling options it represents, is to be + # regarded as experimental. + + } + + + ## environment: describes possible dependency of a test result + ## on the environment within which the test is run. + environment = element environment { + external-atts, + empty + + # The 'environment' element works much + # the same way as the options element; + # when results reported for a test + # depend on the environment (e.g. which + # version of Java is used, or which + # browser an in-browser processor uses, + # or ...), then the relevant + # information should be given on an + # 'environment' element wrapped in an + # 'app-info' element at the appropriate + # level of the test results. (Top + # level if applicable to all, test set + # if applicable only to that test set, + # test result if applicable to that + # result.) + + + } + + # The difference between options and environment is that + # options are assumed to be settable at parse time by whoever + # calls the ixml processor, and the environment is less + # likely to be settable that way. In case of gray areas, + # explain your usage in the test catalog. + + ## dependencies: identifies conditions that must hold for the + ## results given for a test to hold. + dependencies = element dependencies { + attribute Unicode-version { text }, + external-atts, + empty + + # Like 'options' and 'environment', it + # allows an arbitrary set of + # name/value pairs + # (namespace-qualified attributes). + # If all of them apply, the test + # result given is applicable. + + # Some dependencies are standardized: + # any processor must conform to some + # version of Unicode but we don't + # specify which, so the processor must + # specify. Test results must be + # labeled with the appropriate Unicode + # version(s). + + } + + # The differences among these three elements for describing + # when a test or a result is relevant are: + + # options - implementation-defined, typically settable by + # caller at parse time. Wrap in app-info to label + # results (often non-standard) which depend on how + # the processor was invoked. + + # environment - relevant but not under implementation + # control. Wrap in app-info, use to label results + # which depend on the environment within which the + # processor is running (or within which a test + # result was obtained). + + # dependencies - used to label test cases whose results + # depend on which version of another spec is + # applicable. + + } + div { + + # test-set, test-set-results + + # A test set is a collection of tests (or possibly + # subordinate test sets, or both) with common metadata and a + # common grammar. + + # Test cases are allowed only after a grammar is specified. + + # We keep track of whether an ancestor has specified a + # grammar by having two nonterminals for test sets: + # test-set-0 is used when no ancestor has specified a + # grammar, test-set-1 when at least one grammar has been + # specified. + + # If no ancestor has specified a grammar, test cases are + # allowed in this test set only if this test set does specify + # a grammar. Use test-set-0 or -1 to pass the news along. + + ## test-set (pattern test-set-0): a test set with no + ## grammar inherited from any ancestor. + test-set-0 = element test-set { + attribute name { text }, + external-atts, + (Metadata + & + (History, + ( (test-set-0 | test-set-ref)* + | (Grammar-spec, + (test-set-1 + | test-set-ref + | test-case)*) ))) + } + + # If an ancestor has specified a grammar, test cases are allowed + # in this test set even if there is no grammar at this level. + + ## test-set (pattern test-set-1): a test set with a grammar + ## inherited from an ancestor. + test-set-1 = element test-set { + attribute name { text }, + external-atts, + (Metadata + & + (History, + Grammar-spec?, + (test-set-1 | test-set-ref | test-case)*)) + } + + ## test-set-ref: a reference to a test set located in + ## another test catalog; the 'href' attribute gives the URI. + test-set-ref = element test-set-ref { + external-atts, + attribute href { xsd:anyURI } + } + + ## test-set-results: contains reports of results from running + ## the test cases of a given test set. + test-set-results = element test-set-results { + attribute name { text }, + external-atts, + (Metadata + & + (Grammar-results?, + (test-set-results | test-result)*)) + } + + } + div { + + # Specifying the grammar for a set of tests + + # Grammars can be in invisible XML or in visible XML. They + # can be inline or external. They can be marked as a grammar + # test or not. + + ## Grammar-data: four ways to specify the grammar for a test + ## set. + Grammar-data = (ixml-grammar + | vxml-grammar + | ixml-grammar-ref + | vxml-grammar-ref) + + ## Grammar-spec: specification of the grammar for a test set, + ## optionally treating the grammar itself as a test case to + ## be parsed against the specification grammar. + Grammar-spec = (Grammar-data, grammar-test?) + + # In the results file, we may omit the grammar, or include + # it, possibly both reproducing the reference and giving + # the grammar inline. + + ## Grammar-results: optional reproduction of the grammar used + ## for the test set, and reports of any grammar tests. + Grammar-results = (Grammar-data*, grammar-result*) + + # Q. Why is the grammar optional? + # A. Because in a nested test set we may want to inherit the + # grammar from the parent test set. In a top-level test + # set with no direct test-case children, we may just be + # pointing to multiple test sets which each provide their + # own grammar. By the time we reach a test case we must + # have at least one grammar, but we don't need one at + # every level. + + # Q. Why can't there be multiple grammars? + # A. First, it's error prone: it would work only if all of + # them were guaranteed equivalent. We don't want to have + # to check that, and we don't want the mess that will + # result if it turns out not to be true. Second, it + # complicates reporting unnecessarily. It's simpler when + # one test case is one grammar + input + result triple. + + ## ixml-grammar: a grammar in invisible-XML form, given + ## inline in the test catalog. + ixml-grammar = element ixml-grammar { + external-atts, + text + } + + ## ixml-grammar-ref: a reference to a grammar in + ## invisible-XML form located elsewhere. The 'href' + ## attribute says where. + ixml-grammar-ref = element ixml-grammar-ref { + external-atts, + attribute href { xsd:anyURI } + } + + ## vxml-grammar: grammar in visible-XML form (either a parsed + ## ixml grammar, translated into XML, or something created in + ## XML), given inline in the test catalog. + vxml-grammar = element vxml-grammar { + external-atts, + any-element + } + + # N.B. It is tempting to embed a schema for ixml grammars here + # to enforce the correct XML form. But we do not require a + # legal ixml grammar, because it may be a negative test case. + + ## vxml-grammar-ref: reference to a grammar in visible-XML + ## form (either a parsed ixml grammar, translated into XML, + ## or something created in XML), given elsewhere (as + ## indicated by the 'href' attribute). + vxml-grammar-ref = element vxml-grammar-ref { + external-atts, + attribute href { xsd:anyURI } + } + + ## grammar-test: signals that this grammar should be checked + ## and either accepted or declined as a grammar. + grammar-test = element grammar-test { + external-atts, + (Metadata & (History?, result)) + } + + ## grammar-result: reports the result of a grammar test. + grammar-result = element grammar-result { + attribute result { result-type }, + external-atts, + (Metadata & (result-report?)) + } + } + div { + # test-case + + ## test-case: describes one test case, with metadata, + ## history, and expected result. + test-case = element test-case { + attribute name { text }, + external-atts, + (Metadata & (History?, Test-string, result)) + } + + ## test-result: reports the result of one test case. + test-result = element test-result { + attribute name { text }, + attribute result { result-type }, + external-atts, + (Metadata & + (Grammar-data*, + (Test-string)*, + result-report?) + ) + } + + ## result-type: keyword description of test result + result-type = ## results are as expected + 'pass' + | ## results not as expected + 'fail' + | ## right overall result, wrong error code + 'wrong-error' + | ## right overall result, wrong ixml:state value(s) + 'wrong-state' + | ## test case was not run (explain!) + 'not-run' + | ## none of the above + 'other' + + ## Test-string: input string, in-line or external + Test-string = (test-string | test-string-ref) + + ## test-string: this element contains the input string + ## for the test case. + test-string = element test-string { + external-atts, + text + } + + ## test-string-ref: this element carries a point to an + ## external resource which contains the input string for the + ## test case. + test-string-ref = element test-string-ref { + external-atts, + attribute href { xsd:anyURI } + } + } + div { + # result + + ## result: specifies the expected result of a test; contains + ## an assertion of some kind. + result = element result { + external-atts, + Assertion + } + + ## result-report: specifies the observed result of running a + ## test case. May repeat the assertion describing the + ## expected result, and may report what was actually observed + ## when the test was run. + result-report = element result { + external-atts, + Assertion?, + Observation? + } + + } + div { + # Test assertions + + # Several kinds of result are possible. + # + # - In the common case we will have one expected XML result. + # We specify it with assert-xml or assert-xml-ref (inline + # or external). + # + # - For ambiguous sentences, we may and should specify + # several XML results, any of which is acceptable. So the + # XML assertions can repeat, with an implicit OR as their + # meaning. + # + # - In the case of infinite ambiguity, we can and should + # specify a finite subset of the expected results, which we + # add to as needed. + # + # - If the input is not be a sentence in the language defined + # by the grammar, we use assert-not-a-sentence. + # + # - If the grammar specified is not a conforming ixml + # grammar, then we use assert-not-a-grammar. + # + # - If the particular grammar + input pair would produce + # ill-formed output if the normal rules were followed, then + # we use assert-dynamic-error. + # + # Logically speaking, in the case of a grammar-test, there is + # no useful distinction between assert-not-a-sentence and + # assert-not-a-grammar. Casuists can argue over which makes + # more sense, but in practice they should be treated as + # equivalent. The two assertions are usefully different only + # for normal test cases. + # + # Since dynamic errors are allowed to be caught statically, + # some processors may return assert-not-a-grammar when the + # test catalog expects assert-dynamic-error. + # + # Errors in the grammar and dynamic errors may be associated + # with error codes. These are now required. + + ## Assertion: things a catalog can say about an expected test + ## result. + Assertion = ((assert-xml-ref | assert-xml)+ + | assert-not-a-sentence + | assert-not-a-grammar + | assert-dynamic-error) + + ## Error-Code: an attribute for specifying an error code + ## expected for a test case, or observed in a test. + Error-Code = attribute error-code { text } + + ## assert-xml-ref: asserts that the result of the test case + ## is expected to match the external XML document pointed to + ## by the 'href' attribute. + assert-xml-ref = element assert-xml-ref { + external-atts, + attribute href { xsd:anyURI } + } + + ## assert-xml: asserts that the result of the test case is + ## expected to match the XML contained. + assert-xml = element assert-xml { + external-atts, + any-element+ + } + + ## assert-not-a-sentence: asserts that the input string is + ## not a sentence in the language defined by the input + ## grammar. + assert-not-a-sentence = element assert-not-a-sentence { + external-atts, + Metadata + } + + ## assert-not-a-grammar: asserts that the input grammar given + ## is not a conforming ixml grammar. This may be because + ## it's not a sentence in the language defined by the ixml + ## specification grammar, or for other reasons. + assert-not-a-grammar = element assert-not-a-grammar { + Error-Code, + external-atts, + Metadata + } + + ## assert-dynamic-error: asserts that when the input grammar + ## is parsed against the input grammar and written out as + ## XML, a dynamic error is expected to result. Note that + ## processors are allowed to detect dynamic errors statically + ## and report with a 'reported-not-a-grammar'. + assert-dynamic-error = element assert-dynamic-error { + Error-Code, + external-atts, + Metadata + } + + ## Observation: things a test report can say about + ## an observed test result. + Observation = ((reported-xml-ref | reported-xml)+ + | reported-not-a-sentence + | reported-not-a-grammar + | reported-dynamic-error) + + ## reported-xml-ref: reports that when the test case + ## was run, the processor produced the XML document + ## pointed to by the 'href' attribute. + reported-xml-ref = element reported-xml-ref { + external-atts, + attribute href { xsd:anyURI } + } + + ## reported-xml: reports that when the test case was run, the + ## processor produced the XML output contained in the + ## element. + reported-xml = element reported-xml { + external-atts, + any-element+ + } + + ## reported-not-a-sentence: reports that when the test case + ## was run, the processor reported that parsing failed (i.e. + ## that the input string is not a sentence in the language + ## defined by the input grammar). + reported-not-a-sentence = element reported-not-a-sentence { + external-atts, + Metadata + } + + ## reported-not-a-grammar: reports that when the test case + ## was run, the processor reported that the input grammar + ## was not a conforming ixml grammar. + ## Note that this may be reported when the processor + ## detects that serializing the result would raise a + ## dynamic error. + reported-not-a-grammar = element reported-not-a-grammar { + Error-Code, + external-atts, + Metadata + } + + ## reported-dynamic-error: reports that when the test case + ## was run, the processor reported a dynamic error. + reported-dynamic-error = element reported-dynamic-error { + Error-Code, + external-atts, + Metadata + } - reported-xml-ref = element reported-xml-ref { - external-atts, - attribute href { xsd:anyURI } - } - reported-xml = element reported-xml { - external-atts, - any-element+ - } - reported-not-a-sentence = element reported-not-a-sentence { - external-atts, - Metadata - } - reported-not-a-grammar = element reported-not-a-grammar { - Error-Code, - external-atts, - Metadata - } - reported-dynamic-error = element reported-dynamic-error { - Error-Code, - external-atts, - Metadata - } - - -# Common constructs - - # History: creation and modification history - History = (created, modified*) - - who-when = attribute by { text }, - attribute on { xsd:date } - - created = element created { - who-when - } - - modified = element modified { - who-when, - attribute change { text } - } - - # Elements for simple prose. - - p = element p { phrases } - - phrases = (text | emph | code)* - - emph = element emph { phrases } - - code = element code { text } - - # Arbitrary XML - - anything = (any-element | any-attribute | text)* - any-element = element * { anything } - any-attribute = attribute * { text } - - external-atts = nsq-att* - - nsq-att = attribute (* - unqualified:*) { text } - + } + div { + # Common constructs + + ## History: creation and modification history + History = (created, modified*) + + ## who-when: attributes for reporting who did + ## something and when they did it. + who-when = attribute by { text }, + attribute on { xsd:date } + + ## created: reports who created the item (test catalog, test + ## set, test case, ...) and when. + created = element created { + who-when + } + + ## modified: reports who changed the item (test catalog, test + ## set, test case, ...) and when. + modified = element modified { + who-when, + attribute change { text } + } + + # Elements for simple prose. + + ## p: a paragraph of simple prose. + p = element p { phrases } + + ## phrases: possible content of a paragraph. + phrases = (text | emph | code)* + + ## emph: marks a phrased emphasized either rhetorically or + ## typographically or both. (Expected rendering: italic.) + emph = element emph { phrases } + + ## code: marks material from a machine-processable language + ## of some kind (e.g. a program). (Expected rendering: + ## monospaced.) + code = element code { text } + + # Arbitrary XML + + ## anything: a pattern matching arbitrary XML + anything = (any-element | any-attribute | text)* + + ## any-element: a pattern matching one well-formed XML + ## element. + any-element = element * { anything } + + ## any-element: a pattern matching one XML attribute. + any-attribute = attribute * { text } + + ## external-atts: a pattern matchine zero or more + ## namespace-qualified attributes. + external-atts = nsq-att* + + ## nsq-att: a pattern matching one namespace-qualified + ## attribute. + nsq-att = attribute (* - unqualified:*) { text } + + } } From f5c86670511d9ccdc92176a3f5a206382a47292f Mon Sep 17 00:00:00 2001 From: "C. M. Sperberg-McQueen" Date: Tue, 28 May 2024 18:12:17 -0600 Subject: [PATCH 2/2] First checkin of work on TSDs --- tools/tsd/images/tsd-workflow.dot | 27 + tools/tsd/images/tsd-workflow.dot.png | Bin 0 -> 52451 bytes tools/tsd/images/tsd-workflow.dot.svg | 139 +++++ tools/tsd/rng-to-TSD.xsl | 632 +++++++++++++++++++++++ tools/tsd/tsd-planning.html | 700 ++++++++++++++++++++++++++ tools/tsd/tsd-planning.org | 332 ++++++++++++ 6 files changed, 1830 insertions(+) create mode 100644 tools/tsd/images/tsd-workflow.dot create mode 100644 tools/tsd/images/tsd-workflow.dot.png create mode 100644 tools/tsd/images/tsd-workflow.dot.svg create mode 100644 tools/tsd/rng-to-TSD.xsl create mode 100644 tools/tsd/tsd-planning.html create mode 100644 tools/tsd/tsd-planning.org diff --git a/tools/tsd/images/tsd-workflow.dot b/tools/tsd/images/tsd-workflow.dot new file mode 100644 index 00000000..80b7b282 --- /dev/null +++ b/tools/tsd/images/tsd-workflow.dot @@ -0,0 +1,27 @@ +digraph tsd_dfd { + // sketch of a data flow for managing tag set documentation + + subgraph { + node [shape=box]; + + rnc [label="RNC schema"]; + rng [label="RNG\n(auto-generated)"]; + auto [label="auto-TSD\n(tag-set description\n=Docbook refentry+\nauto-generated)"]; + manual [label="manual TSD\n(tag-set description\n=Docbook refentry+\neditable)" fontcolor=red]; + // tsd [label="TSD\n(partly editable)"]; + tsd [label="TSD\n(tag-set description:\nDocbook refentry+\nprose and auto-generated)"]; + + node [shape=oval]; + // editrnc [label="edit / regen"]; + edittsd [label="edit"]; + manual -> edittsd -> manual; + tsdxrng [label="auto-generate TSD"]; + merge [label="merge\nauto- and manual parts"]; + rnc -> trang -> rng -> tsdxrng -> auto -> merge -> tsd; + manual -> merge; + subgraph { rank = same; auto; manual; } + } + // rnc -> editrnc -> rnc [weight=0]; + tsd -> manual [style=dotted weight=0 label="Re-use"]; + +} diff --git a/tools/tsd/images/tsd-workflow.dot.png b/tools/tsd/images/tsd-workflow.dot.png new file mode 100644 index 0000000000000000000000000000000000000000..6f9cb809261284157d5df8e32a53b6eb2291a8d7 GIT binary patch literal 52451 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 Wo+s&5-Q;f*&6qaJ;;gw#(0>6*%ft@= literal 0 HcmV?d00001 diff --git a/tools/tsd/images/tsd-workflow.dot.svg b/tools/tsd/images/tsd-workflow.dot.svg new file mode 100644 index 00000000..e990ecce --- /dev/null +++ b/tools/tsd/images/tsd-workflow.dot.svg @@ -0,0 +1,139 @@ + + + + + + +tsd_dfd + + + +rnc + +RNC schema + + + +trang + +trang + + + +rnc->trang + + + + + +rng + +RNG +(auto-generated) + + + +tsdxrng + +auto-generate TSD + + + +rng->tsdxrng + + + + + +auto + +auto-TSD +(tag-set description +=Docbook refentry+ +auto-generated) + + + +merge + +merge +auto- and manual parts + + + +auto->merge + + + + + +manual + +manual TSD +(tag-set description +=Docbook refentry+ +editable) + + + +edittsd + +edit + + + +manual->edittsd + + + + + +manual->merge + + + + + +tsd + +TSD +(tag-set description: +Docbook refentry+ +prose and auto-generated) + + + +tsd->manual + + +Re-use + + + +edittsd->manual + + + + + +tsdxrng->auto + + + + + +merge->tsd + + + + + +trang->rng + + + + + diff --git a/tools/tsd/rng-to-TSD.xsl b/tools/tsd/rng-to-TSD.xsl new file mode 100644 index 00000000..a5dc3422 --- /dev/null +++ b/tools/tsd/rng-to-TSD.xsl @@ -0,0 +1,632 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tag set documentation for + + + + + + + + + + + + + auto-generated from schema by rng-to-TSD.xsl + + + + + + + + + Introduction + + + This is a skeletal framework for documentation of + + . + It was generated automatically from the + schema by rng-to-TSD.xsl, + on + + at + + . + + + + + + + + + Alphabetical list of elements and patterns + + + + + + + + + + + + + Alphabetical list of elements + + + + + + + + + + + + Alphabetical list of patterns + + + + + + + + + + + + + + + + + + + + Tag set documentation for + + + + + + [None. This tag set documentation + will not be distributed in this form.] + + + + + + + + Generated automatically from + + + + + + + + + Document auto-generated from schema by rng-to-TSD.xsl + + + + + + + + + + Reference documentation (skeleton) + + + for + + + + + + + + + + + + + + Introduction + + + This is a skeletal framework for documentation of + + . + It was generated automatically from the + schema by rng-to-TSD.xsl, + on + + at + + . + + + + + + + + + Alphabetical list of elements and patterns + + + + + + + + + + + + + Alphabetical list of elements + + + + + + + + + + + Alphabetical list of patterns + + + + + + + + + + + + + + + + + + + + Tag set documentation for + + + + + + + + + + + + + + + + + + + + + Reference documentation (skeleton) + for + + + + + + + + + + + Introduction + + + This is a skeletal framework for documentation of + + . + It was generated automatically from the + schema by rng-to-TSD.xsl, + on + + at + + . + + + + + + + + + Alphabetical list of elements and patterns + + + + + + + + + + + + + Alphabetical list of elements + + + + + + + + + + + Alphabetical list of patterns + + + + + + + + + + + + + + + + + + + + + + + + + + + + (element) + + + + + + + + + + + [Description to be supplied.] + + + + + + + + + + + + + + Remarks + + + ... + + + + + + + + + + + + + + + + + + [Description to be supplied.] + + + + + + + + + ... + + + + + + + + + + + + + + + + + + + + + + (element) + + + + + + + + + + [Description to be supplied.] + + + + + + + + + watch this space + + + + + + + + Remarks + + + ... + + + + + + + + + + + + + + + + + + + + + (pattern) + + + + + + + + + + + + + + + + + + Remarks + + + ... + + + + + + + + + + + + + + + + + + + + ... + + + + + + + + + + + + + + + + + + + + + + (pattern) + + + + + + + + + + + + watch this space + + + + + + + + Remarks + + + ... + + + + + + + + + diff --git a/tools/tsd/tsd-planning.html b/tools/tsd/tsd-planning.html new file mode 100644 index 00000000..9bdddaaa --- /dev/null +++ b/tools/tsd/tsd-planning.html @@ -0,0 +1,700 @@ + + + + + + + +Tag set documentation project + + + + + +
+

Tag set documentation project

+
+

+This document outlines a plan for a workflow to create and maintain +documentation for the XML vocabulary used for the XML form of ixml +grammars (here called VXML), and the XML vocabulary used for test +catalogs by the ixml Community Group. +

+ +

+In its current form this document is not complete and is binding on +no one. It is written to serve as a basis for discussion, and to +record some thoughts and expectations. +

+ +
+

1. Project overview

+
+
+
+

1.1. Primary deliverables

+
+

+The central deliverables are reference tag-set documentation (TSD) for +the XML vocabularies in question. +

+ +

+The tag-set documentation we wish to create consists of some +expository prose and a reference pages for the element types and +widely used attributes. +

+ +

+The crucial delivery format is XHTML; other XML vocabularies may be +used for maintenance, but is not expected to be of interest to others. +

+
+
+ +
+

1.2. Requirements

+
+

+Known requirements and desiderata: +

+
    +
  • It must be possible to update the documentation more or less +conveniently as the schemas change.
  • +
  • When the schema changes, human-supplied prose must be carried +forward easily.
  • +
  • Information derivable from the schema should be provided +automatically. Specifically: declarations, lists of parents, +lists of children, lists of attributes.
  • +
  • When schema-derived information changes, it is desirable that +the user be warned, so that any relevant prose can also be +updated.
  • +
+
+
+ +
+

1.3. Workflow

+
+

+The intended workflow is described in this diagram: +

+ +
+

tsd-workflow.dot.png +

+

Figure 1: Workflow plan

+
+ +

+That is: +

+
    +
  • +The RNC/RNG schemas are maintained independently. +

    + +

    +The test catalog schema is maintained by hand in RNC; the ixml +schema is generated automatically in RNG from the ixml grammar, +which is maintained by hand. We use trang to make an RNG form of +the test catalog schema, and an RNC form of the ixml schema. +

    + +

    +Not shown: we use jing -s to create a 'simplified' version of the +RNG schema. In some cases, this may require some hand work. (Jing +aborts with an error message if asked to simplify some schemas with +recursive patterns. The simplified schema also uses some rather +opaque names for patterns introduced by Jing.)) +

  • + +
  • +An XSLT stylesheet (rng-to-TSD.xsl) auto-generates tag-set +documentation for the schema. +

    + +

    +If names and short descriptions are provided in the RNG annotation +namespace (a:documentation elements), they should be carried over. +Otherwise, dummies should be provided. +

    + +

    +This stylesheet draws information about the vocabulary from both the +RNG schema and the simplified RNG schema. +

  • + +
  • An XSLT stylesheet (tsd-merger.xsl) reads the auto-generated +documentation and the previous hand-edited version of the same +documentation, and produces merged output. +
      +
    • For schema-derived information, the auto-generated documentation +is preferred; for other information (basically: the prose), +the hand-edited documentation is preferred.
    • +
    • If any schema-derived information differs between the two +sources, the stylesheet should report the fact to the user.
    • +
  • + +
  • An XSLT stylesheet (tsd-to-html.xsl) reads the merged tag-set +documentation and generates HTML with an appropriate stylesheet +(tsd.css).
  • +
+
+
+ +
+

1.4. Secondary deliverables

+
+

+We have some secondary deliverables, whose purpose is to occupy +the corresponding positions in the workflow. +

+ +
    +
  • Specification of the tag-set documentation vocabulary and +conventions to be used. Obvious candidates are Docbook, TEI P3, TEI +P5, and an ad hoc custom vocabulary.
  • + +
  • auto-tsd.xsl
  • + +
  • tsd-merger.xsl
  • + +
  • tsd-to-html.xsl
  • + +
  • tsd.css
  • +
+
+
+
+ +
+

2. Vocabulary for tag-set documentation

+
+

+We will use Docbook for the XML form of the tag-set documentation. +

+ +

+Because Docbook's reference entries are rather generic, it may be +helpful to specify the pattern to be followed there in more detail. +Each refentry element should contain: +

+ +
    +
  • refnamediv +
      +
    • refdescriptor containing either "(element)" or "(attribute)" or +"(pattern)"
    • +
    • refname with the element type name, attribute name, or pattern +name
    • +
    • refpurpose containing (a) an unabbreviated form of the element +type name, (b) a colon, and (c) a short description (typically one line) +of the meaning or use of the construct
    • +
  • +
  • refsynopsisdiv +
      +
    • +synopsis role="rng-raw" +

      +
        +
      • info containing the 'raw' Relax NG declaration for the +construct: +
          +
        • For elements, the rng:element element.
        • +
        • For attributes, the rng:attribute element.
        • +
        • For patterns, the rng:define element.
        • +
      • +
      +

      +For comparison: this is similar to inclusion of an element +declaration from a DTD with parameter entity references +unexpanded. +

    • +
    • synopsis role="rng-simplified" (for elements and attributes only) +containing the corresponding declaration from the 'simplified' +for the construct. +For comparison: this is similar to inclusion of an element +declaration from a DTD with all parameter entity references +expanded.
    • +
    • (optional, for elements) synopsis role="structured" containing a +structured description in English of the content model of the +element. Not required, because in the usual case an English +summary can be generated from the simplified RNG without trouble. +Not forbidden, because it may be better to do this upstream rather +than in the creation of the HTML delivery form.
    • +
  • +
  • (optional, for elements) refsection entitled "Contents" containing +a prose description in English of the allowed contents of the +element. element. Not required, because not always useful.
  • +
  • (for attributes) refsection entitled "Data description" +with informal prose description of the attribute's datatype.
  • +
  • (for elements) refsection entitled "Attributes" listing all +attributes defined for the element. If the attribute is used on +more than one element, then we want just the attribute name with a +hyperlink to the reference entry for the attribute; if the attribute +is used only on this element, or should be given custom +documentation for this parent, a version of the documentation +pattern for attributes (perhaps attenuated) should be given.
  • +
  • (optional) refsection entitled "Remarks" with prose describing +relevant information – whatever the user will need to know. For +elements and attributes this includes recognition criteria, +distinctions from similar elements or attributes, usage.
  • +
  • refsection entitled "Examples" with prose and examples. In +some cases, this may just consist of references to examples +given in other reference entries.
  • +
  • (optional) refsection entitled "Processing expectations".
  • +
+ +

+For example: +

+
+
<refentry xml:id="element.assert-xml">
+   <refnamediv>
+      <refdescriptor>(element)</refdescriptor>
+      <refname>assert-xml</refname>
+      <refpurpose>Assert-xml:  asserts that the expected
+      output of a conforming ixml processor will be (or,
+      in cases of ambiguity, may be) the child element
+      of the /assert-xml/ element.</refpurpose>
+   </refnamediv>
+   <refsynopsisdiv>
+     <synopsis role="rng-raw">
+       <info>
+         <element xmlns="http://relaxng.org/ns/structure/1.0"
+                  xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
+                  name="assert-xml">
+            <ref name="external-atts"/>
+            <oneOrMore>
+               <ref name="any-element"/>
+            </oneOrMore>
+         </element>
+       </info>
+     </synopsis>
+     <synopsis role="rng-simplified">
+       <info>
+         <element xmlns="http://relaxng.org/ns/structure/1.0"
+                  xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
+                  name="assert-xml">
+           <group>
+             <zeroOrMore>
+               <attribute>
+                 <anyName>
+                   <except>
+                     <nsName ns=""/>
+                   </except>
+                 </anyName>
+                 <text/>
+               </attribute>
+             </zeroOrMore>
+             <oneOrMore>
+               <ref name="_1"/>
+             </oneOrMore>
+           </group>
+         </element>
+       </info>
+     </synopsis>
+   </refsynopsisdiv>
+   <refsection>
+      <title>Contents</title>
+      <para>Any well-formed XML</para>
+   </refsection>
+   <refsection>
+      <title>Remarks</title>
+      <para>If the test catalog has a default namespace
+      declaration, it will be necessary to undeclare it in order
+      to avoid namespace capture of the asserted result. (IXML
+      output has no identified namespace.)</para>
+      <para>When comparing output of an ixml processor to the
+      asserted result, namespace declarations are to be
+      ignored.</para>
+   </refsection>
+</refentry>  
+
+
+
+
+ +
+

3. Auto-generation of TSD (auto-tsd.xsl)

+
+

+[To be drafted.] +

+
+
+ +
+

4. Merger of TSDs (tsd-merger.xsl)

+
+

+[To be drafted.] +

+
+
+ +
+

5. HTML translation and display (tsd-to-html.xsl and tsd.css)

+
+

+[To be drafted.] +

+
+
+ +
+

6. Related work

+
+

+There has been reference documentation for SGML and XML tag sets for +about as long as there have been SGML and XML tag sets intended for +serious use, but there has been very little standardization on the +form of such documentation. Among the examples which have influenced +this work are: +

+ +
    +
  • +Formex (1985). Formex served "formalized exchange of electronic +publications". The manual includes expository prose reference +documentation includes two lists of data elements, one for a format +called CCF (common communications format, an implementation of +ISO 2079) and one for an SGML document type definition. The +reference page for each element type includes: +

    +
      +
    • A symbolic representation of the element's generic identifier +(element type name) and attributes e.g. <AB LA = ...> for +the AB (abstract) element with its LA (language) attribute.
    • +
    • A definition (or terse prose description) of the element.
    • +
    • A data description of the element, describing its content and +format.
    • +
    • A usage note specifying whether the element is mandatory or +optional, repeatable or non-repeatable.
    • +
    • A grouping note specifying what 'groups' the element is part +of (this appears to be a list of possible parents or possibly +higher-level containers).
    • +
    • An example (not always present).
    • +
    +

    +For each attribute, the reference page gives: +

    +
      +
    • A definition (or terse prose description) of the attribute.
    • +
    • A data description defining the set of possible attribute +values.
    • +
    +

    +Not listed here but prominent on each page are cross references to +the corresponding CCF data elements. +

  • + +
  • Maler and El Andaloussi (1996). Maler and El Andaloussi recommend +the following as the "minimal information" for element reference +documentation: +
      +
    • Short name or actual generic identifier (e.g. olist).
    • +
    • Full name: descriptive phrase that explains the short name +(e.g. "An ordered list of related items.").
    • +
    • Synopsis: rules for using the element, perhaps including tree +diagrams showing possible parents and children.
    • +
    • Description: purpose, how and where it should be used, +recognition criteria, etc.
    • +
    • Attributes: reference description for each attribute.
    • +
    • Contents and Contexts (if not already present in the description +and if not clearly conveyed by the synopsis).
    • +
    • Examples.
    • +
    • Processing notes, including notes on how to work around +shortcomings in current tools.
    • +
  • + +
  • +JATS documentation (current). This is a reasonably typical example +of the tag-set documentation supplied by at least some commercially +active SGML and XML consultants. Reference material for an element +includes: +

    +
      +
    • Generic identifier / element type name
    • +
    • Full name
    • +
    • Annotation (to specify which DTDs in a set contain the element)
    • +
    • Definition
    • +
    • Remarks
    • +
    • Related elements
    • +
    • Content model
    • +
    • Content description (prose)
    • +
    • Presentation information (expected styling)
    • +
    • Examples (with prose commentary)
    • +
    • Related resources (pointers to other relevant information)
    • +
    • Source (if adapted from some other tag set)
    • +
    • Module (in a multi-module vocabulary)
    • +
    • Revision history
    • +
    +

    +There are similar structures for attributes and parameter entities. +

  • + +
  • +TEI P3 (1994). The auxiliary document type for 'tag set +documentation' allows for each element type: +

    +
      +
    • generic identifier
    • +
    • full name
    • +
    • short description (typically a one-liner)
    • +
    • list of attributes (with reference information for each)
    • +
    • examples (with commentary and explanation)
    • +
    • remarks
    • +
    • information on the part of TEI where the element is defined, +the classes it belongs to, and the file(s) it is defined in
    • +
    • a data description (in prose)
    • +
    • a list of parents
    • +
    • a list of children
    • +
    • the text of the element's declaration
    • +
    • the text of the element's attribute-list declaration
    • +
    • hyperlinks to relevant documentation
    • +
    • a list of equivalent elements (in other vocabularies)
    • +
    +

    +TEI P5 (current) has modified the tag-set documentation of P3 and +made many of the elements less specific. +

  • +
+ +

+The reference material of Docbook has also had an obvious influence. +

+
+
+ +
+

7. References

+
+
    +
  • Formex: formalized exchange of electronic publications, +ed. C. Guittet. Luxembourg: Office for Official Publications of the +European Communities, 'New Technologies – Project Management' +Department, 1985. 243 pp.
  • + +
  • Maler, Eve, and Jeanne El Andaloussi. Developing SGML DTDs: from +text to model to markup. Upper Saddle River, NJ: Prentice Hall PTR, +
      +
    1. +
  • +
+
+
+
+
+

Date: 28 May 2024

+

Author: CMSMcQ

+

Created: 2024-05-28 Tue 18:10

+

Validate

+
+ + diff --git a/tools/tsd/tsd-planning.org b/tools/tsd/tsd-planning.org new file mode 100644 index 00000000..5c5391ed --- /dev/null +++ b/tools/tsd/tsd-planning.org @@ -0,0 +1,332 @@ +#+title: Tag set documentation project +#+author: CMSMcQ +#+date: 28 May 2024 +#+ORG-IMAGE-ACTUAL-WIDTH: nil + +This document outlines a plan for a workflow to create and maintain +documentation for the XML vocabulary used for the XML form of ixml +grammars (here called VXML), and the XML vocabulary used for test +catalogs by the ixml Community Group. + +In its current form this document is not complete and /is binding on +no one/. It is written to serve as a basis for discussion, and to +record some thoughts and expectations. + +* Project overview +** Primary deliverables +The central deliverables are reference tag-set documentation (TSD) for +the XML vocabularies in question. + +The tag-set documentation we wish to create consists of some +expository prose and a reference pages for the element types and +widely used attributes. + +The crucial delivery format is XHTML; other XML vocabularies may be +used for maintenance, but is not expected to be of interest to others. + +** Requirements +Known requirements and desiderata: +- It must be possible to update the documentation more or less + conveniently as the schemas change. +- When the schema changes, human-supplied prose must be carried + forward easily. +- Information derivable from the schema should be provided + automatically. Specifically: declarations, lists of parents, + lists of children, lists of attributes. +- When schema-derived information changes, it is desirable that + the user be warned, so that any relevant prose can also be + updated. + +** Workflow +The intended workflow is described in this diagram: +#+CAPTION: Workflow plan +#+ATTR_HTML: width: 25% +[[./images/tsd-workflow.dot.png]] + +That is: +- The RNC/RNG schemas are maintained independently. + + The test catalog schema is maintained by hand in RNC; the ixml + schema is generated automatically in RNG from the ixml grammar, + which is maintained by hand. We use trang to make an RNG form of + the test catalog schema, and an RNC form of the ixml schema. + + Not shown: we use /jing -s/ to create a 'simplified' version of the + RNG schema. In some cases, this may require some hand work. (Jing + aborts with an error message if asked to simplify some schemas with + recursive patterns. The simplified schema also uses some rather + opaque names for patterns introduced by Jing.)) + +- An XSLT stylesheet (/rng-to-TSD.xsl/) auto-generates tag-set + documentation for the schema. + + If names and short descriptions are provided in the RNG annotation + namespace (/a:documentation/ elements), they should be carried over. + Otherwise, dummies should be provided. + + This stylesheet draws information about the vocabulary from both the + RNG schema and the simplified RNG schema. + +- An XSLT stylesheet (/tsd-merger.xsl/) reads the auto-generated + documentation and the previous hand-edited version of the same + documentation, and produces merged output. + + For schema-derived information, the auto-generated documentation + is preferred; for other information (basically: the prose), + the hand-edited documentation is preferred. + + If any schema-derived information differs between the two + sources, the stylesheet should report the fact to the user. + +- An XSLT stylesheet (/tsd-to-html.xsl/) reads the merged tag-set + documentation and generates HTML with an appropriate stylesheet + (tsd.css). + +** Secondary deliverables + +We have some secondary deliverables, whose purpose is to occupy +the corresponding positions in the workflow. + +- Specification of the tag-set documentation vocabulary and + conventions to be used. Obvious candidates are Docbook, TEI P3, TEI + P5, and an ad hoc custom vocabulary. + +- /auto-tsd.xsl/ + +- /tsd-merger.xsl/ + +- /tsd-to-html.xsl/ + +- /tsd.css/ + +* Vocabulary for tag-set documentation +We will use Docbook for the XML form of the tag-set documentation. + +Because Docbook's reference entries are rather generic, it may be +helpful to specify the pattern to be followed there in more detail. +Each /refentry/ element should contain: + +- /refnamediv/ + + /refdescriptor/ containing either "(element)" or "(attribute)" or + "(pattern)" + + /refname/ with the element type name, attribute name, or pattern + name + + /refpurpose/ containing (a) an unabbreviated form of the element + type name, (b) a colon, and (c) a short description (typically one line) + of the meaning or use of the construct +- /refsynopsisdiv/ + + /synopsis role="rng-raw"/ + - /info/ containing the 'raw' Relax NG declaration for the + construct: + + For elements, the /rng:element/ element. + + For attributes, the /rng:attribute/ element. + + For patterns, the /rng:define/ element. + For comparison: this is similar to inclusion of an element + declaration from a DTD with parameter entity references + unexpanded. + + /synopsis role="rng-simplified"/ (for elements and attributes only) + containing the corresponding declaration from the 'simplified' + for the construct. + For comparison: this is similar to inclusion of an element + declaration from a DTD with all parameter entity references + expanded. + + (optional, for elements) /synopsis role="structured"/ containing a + structured description in English of the content model of the + element. Not required, because in the usual case an English + summary can be generated from the simplified RNG without trouble. + Not forbidden, because it may be better to do this upstream rather + than in the creation of the HTML delivery form. +- (optional, for elements) /refsection/ entitled "Contents" containing + a prose description in English of the allowed contents of the + element. element. Not required, because not always useful. +- (for attributes) /refsection/ entitled "Data description" + with informal prose description of the attribute's datatype. +- (for elements) /refsection/ entitled "Attributes" listing all + attributes defined for the element. If the attribute is used on + more than one element, then we want just the attribute name with a + hyperlink to the reference entry for the attribute; if the attribute + is used only on this element, or should be given custom + documentation for this parent, a version of the documentation + pattern for attributes (perhaps attenuated) should be given. +- (optional) /refsection/ entitled "Remarks" with prose describing + relevant information -- whatever the user will need to know. For + elements and attributes this includes recognition criteria, + distinctions from similar elements or attributes, usage. +- /refsection/ entitled "Examples" with prose and examples. In + some cases, this may just consist of references to examples + given in other reference entries. +- (optional) /refsection/ entitled "Processing expectations". + +For example: +#+begin_src Docbook-xml + + + (element) + assert-xml + Assert-xml: asserts that the expected + output of a conforming ixml processor will be (or, + in cases of ambiguity, may be) the child element + of the /assert-xml/ element. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Contents + Any well-formed XML + + + Remarks + If the test catalog has a default namespace + declaration, it will be necessary to undeclare it in order + to avoid namespace capture of the asserted result. (IXML + output has no identified namespace.) + When comparing output of an ixml processor to the + asserted result, namespace declarations are to be + ignored. + + +#+end_src + +* Auto-generation of TSD (/auto-tsd.xsl/) +[To be drafted.] + +* Merger of TSDs (/tsd-merger.xsl/) +[To be drafted.] + +* HTML translation and display (/tsd-to-html.xsl/ and /tsd.css/) +[To be drafted.] + +* Related work +There has been reference documentation for SGML and XML tag sets for +about as long as there have been SGML and XML tag sets intended for +serious use, but there has been very little standardization on the +form of such documentation. Among the examples which have influenced +this work are: + +- Formex (1985). Formex served "formalized exchange of electronic + publications". The manual includes expository prose reference + documentation includes two lists of data elements, one for a format + called CCF (common communications format, an implementation of + ISO 2079) and one for an SGML document type definition. The + reference page for each element type includes: + + A symbolic representation of the element's generic identifier + (element type name) and attributes e.g. ~~ for + the AB (abstract) element with its LA (language) attribute. + + A definition (or terse prose description) of the element. + + A data description of the element, describing its content and + format. + + A usage note specifying whether the element is mandatory or + optional, repeatable or non-repeatable. + + A grouping note specifying what 'groups' the element is part + of (this appears to be a list of possible parents or possibly + higher-level containers). + + An example (not always present). + For each attribute, the reference page gives: + + A definition (or terse prose description) of the attribute. + + A data description defining the set of possible attribute + values. + Not listed here but prominent on each page are cross references to + the corresponding CCF data elements. + +- Maler and El Andaloussi (1996). Maler and El Andaloussi recommend + the following as the "minimal information" for element reference + documentation: + + Short name or actual generic identifier (e.g. ~olist~). + + Full name: descriptive phrase that explains the short name + (e.g. "An ordered list of related items."). + + Synopsis: rules for using the element, perhaps including tree + diagrams showing possible parents and children. + + Description: purpose, how and where it should be used, + recognition criteria, etc. + + Attributes: reference description for each attribute. + + Contents and Contexts (if not already present in the description + and if not clearly conveyed by the synopsis). + + Examples. + + Processing notes, including notes on how to work around + shortcomings in current tools. + +- JATS documentation (current). This is a reasonably typical example + of the tag-set documentation supplied by at least some commercially + active SGML and XML consultants. Reference material for an element + includes: + + Generic identifier / element type name + + Full name + + Annotation (to specify which DTDs in a set contain the element) + + Definition + + Remarks + + Related elements + + Content model + + Content description (prose) + + Presentation information (expected styling) + + Examples (with prose commentary) + + Related resources (pointers to other relevant information) + + Source (if adapted from some other tag set) + + Module (in a multi-module vocabulary) + + Revision history + There are similar structures for attributes and parameter entities. + +- TEI P3 (1994). The auxiliary document type for 'tag set + documentation' allows for each element type: + + generic identifier + + full name + + short description (typically a one-liner) + + list of attributes (with reference information for each) + + examples (with commentary and explanation) + + remarks + + information on the part of TEI where the element is defined, + the classes it belongs to, and the file(s) it is defined in + + a data description (in prose) + + a list of parents + + a list of children + + the text of the element's declaration + + the text of the element's attribute-list declaration + + hyperlinks to relevant documentation + + a list of equivalent elements (in other vocabularies) + TEI P5 (current) has modified the tag-set documentation of P3 and + made many of the elements less specific. + +The reference material of Docbook has also had an obvious influence. + +* References + +- /Formex: formalized exchange of electronic publications/, + ed. C. Guittet. Luxembourg: Office for Official Publications of the + European Communities, 'New Technologies -- Project Management' + Department, 1985. 243 pp. + +- Maler, Eve, and Jeanne El Andaloussi. /Developing SGML DTDs: from + text to model to markup./ Upper Saddle River, NJ: Prentice Hall PTR, + 1996.