Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support inherit #50

Merged
merged 7 commits into from
Aug 24, 2024
Merged

Support inherit #50

merged 7 commits into from
Aug 24, 2024

Conversation

jombr
Copy link
Collaborator

@jombr jombr commented Aug 6, 2024

No description provided.

@coveralls
Copy link

coveralls commented Aug 6, 2024

Coverage Status

coverage: 89.646% (+0.1%) from 89.527%
when pulling ee730a0 on jombr:support-inherit
into b1621e1 on djc:main.

parser.py
Support EBNF from https://relaxng.org/compact-20021121.html
section 2. Syntax:

```
   decl ::= .....
           |"default" "namespace" [identifierOrKeyword] "=" namespaceURILiteral
   ...
   namespaceURILiteral ::= ...
                          | "inherit"
```

serializer.py

If default namespace is inherit don't
write a default ns on top level grammar

For elements, don't write ns="" on name node
if using the default namespace set to inherit

 - https://relaxng.org/compact-tutorial-20030326.html
   Section 10.2. Default namespace
   "A namespace declaration can refer to the null or absent namespace by using a namespace URI of """
   - we don't want to refer to the null or absent namespace, we want to inherit

 - https://relaxng.org/tutorial-20011203.html
   Section 10.1. Using the ns attribute

   "A value of an empty string for the ns attribute indicates a null or absent namespace URI"

   - if we write ns="" for rng xml, it only matches null or absent namespace, not
     whatever is inherited from the default namespace of the referencing file

For attributes, don't do anything different

 - https://relaxng.org/compact-tutorial-20030326.html
   Section 10.2. Default namespace

   "As with XML, the default namespace does not apply to attribute patterns"

 - https://relaxng.org/tutorial-20011203.html
   Section 10.1 Using the ns attribute

   "The attribute pattern also takes an ns attribute.
   However, there is a difference in how it defaults.
   This is because of the fact that the XML Namespaces Recommendation
   does not apply the default namespace to attributes.
   if an ns attribute is not specified on the attribute pattern,
   then it defaults to the empty string."

   - its still OK to set ns="" on attribute name elements.
     It is logically equivalent to remove them but that's
     antithetical to Simplification:
     https://relaxng.org/spec-20011203.htm
     Section 4.8. name attribute of element and attribute elements

     "If an attribute element has a name attribute but no ns attribute,
     then an ns="" attribute is added to the name child element."
default namespace prefix is already supported
but I added a stand alone test case for it
 - it was being tested in relax.rnc but
   I thought a granular case would be
   useful to compare against as
   default namespace prefix = inherit
   case

parser.py
  See reference for production non-terminal namespaceURILiteral
  in https://relaxng.org/compact-20021121.html for sections
  "2. Syntax" or "A. Formal Description 1. Syntax"

  excerpt of EBNF from section 2. Syntax

    decl ::= "default" "namespace" [identifierOrKeyword] "=" namespaceURILiteral
    ...
    namespaceURILiteral ::= literal
                            | "inherit"

  See reference for "RELAX NG Compact Syntax Tutorial"
  https://relaxng.org/compact-tutorial-20030326.html
  Section "16.1 inherit keyword"

serializer.py

   If default namespace prefix is inherit don't
   write a default ns or prefix on top level grammar
    - since Prefixed namespace bindings may not be empty
      see https://www.w3.org/TR/REC-xml-names/#ns-using
      Section 5 Using Qualified Names
      "In a namespace declaration for a prefix
      (i.e., where the NSAttName is a PrefixedAttName),
      the attribute value MUST NOT be empty."

   If there is a prefixed namespace while
   serializing NAME, don't write ns=""
   - since that means not to inherit.

   This doesn't impact serializing NAME when
   the context is within an attribute.
   Writing ns="" would be fine since there is a
   difference how it defaults. It may be
   more consistent to leave the ns="" on the
   attribute but that would add a little more
   code. I also kind of like the behavior
   - If you have a ns prefix inherit no ns="" exists
See reference for production non-terminal namespaceURILiteral
in https://relaxng.org/compact-20021121.html for sections
"2. Syntax" or "A. Formal Description 1. Syntax"

excerpt of EBNF from section 2. Syntax

   decl ::= "namespace" identifierOrKeyword "=" namespaceURILiteral
   ...
   namespaceURILiteral ::= literal
                           | "inherit"

parser.py
 - Add production for declaring a namespace as inherit
   similar to declaring default namespace prefix as inherit

No additional changes for serializer.py
 - if the prefix namespace is inherit don't write
   the ns on the ELEMENT node.
 - As a stand alone file, we can't follow steps in
   https://relaxng.org/spec-20011203.html 4. Simplification
   Specifically 4.10. QNames, "The context must have a mapping for the prefix"
   so we can't do this step, because we don't have a mapping.

Test case added:

   See reference for "RELAX NG Compact Syntax Tutorial"
   https://relaxng.org/compact-tutorial-20030326.html
   Section "16.1 inherit keyword"
   for more examples.

   Added ns-inherit.rnc and ns-inherit.rng
   - no namespaces have been added for the
     element and attribute
   - similar to if "default namespace = inherit (not using a prefix)
     - other than attribute's ns="", since it doesn't
       inherit the default
   - different from no default specified, and no declared ns prefix used
     - element and attribute would have ns="",
       since rnc2html looks to be assuming its a top level grammar
       meaning, per https://relaxng.org/compact-tutorial-20030326.html
       10.2. Default namespace, non-explicitly would match
       the explicit declaration
       - default namespace = ""
https://relaxng.org/compact-20021121.html
Section 2 Syntax

```
decl := "namespace" identifierOrKeyword "=" namespaceURILiteral
       | "default" "namespace" [identifierOrKeyword] "=" namespaceURILiteral

...

namespaceURILiteral := literal
                      | "inherit"
```

Add ns_uri_inh production that handles
 - strlit
 - INHERIT

Update decl's to share the new production
 - decl_default_ns
 - decl_default_names_ns
 - decl_ns
https://relaxng.org/compact-tutorial-20030326.html
Section 10.2 Default namespace

A namespace declaration can refer to the null or
absent namespace by using a namespace URI of ""

A file can ensure that its default namespace will
be the null or absent namespace and will not be
inherited from any referencing file by
explicitly declaring the default namespace as ""

Added Case default-ns-empty.rnc
 - looks a lot like simple.rnc with the addition
   of an attribute

Notice how default-ns-empty.rnc and
simple.rnc have similar ns="" in their
rng conversion without simple.rnc defining
a default namespace.

In https://relaxng.org/compact-tutorial-20030326.html
section 10.2 Default namespace

   If a file does not declare a default namespace and
   is a top-level file that is not referenced from
   another file using include or external, then
   the default namespace is the absent or null namespace.
See https://relaxng.org/compact-20021121.html
4. Declarations

  The URI may be empty. This makes the prefix stand for the absent namespace URI.
  This is necessary for specifying a name class that matches any name with an absent namespace URI.

Updated serializer.py to not write empty
prefixed namespace bindings.
 - see https://www.w3.org/TR/REC-xml-names/#ns-using
   Section 5 Using Qualified Names
   "In a namespace declaration for a prefix
   (i.e., where the NSAttName is a PrefixedAttName),
   the attribute value MUST NOT be empty."

Test Cases:
 - Added defaul-ns-prefix-empty.rnc
 - Added ns-empty.rnc
   - as a simple coverage case.
     relax.rnc also touches this feature
 - Updated relax.rnc
   - It was adding xmlns:local="" but
     that violates qualified names
     requirements.
   - trang-20220510 reports this error when converting relax.rng to rnc:
     fatal: The value of the attribute
     "prefix="xmlns",localpart="local",rawname="xmlns:local"" is invalid.
     Prefixed namespace bindings may not be empty.
A slightly more complex example
showing how inherit and empty (null or absent)
namespace work together
@jombr jombr merged commit 93c87d7 into djc:main Aug 24, 2024
8 checks passed
@jombr jombr deleted the support-inherit branch August 24, 2024 20:20
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.

2 participants