././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1631176377.5354884 rnc2rng-2.6.6/0000755000076500000240000000000000000000000011524 5ustar00djcstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/AUTHORS0000644000076500000240000000036500000000000012600 0ustar00djcstaffDavid Mertz Dirkjan Ochtman Dustin J. Mitchell John Vandenberg Low Kian Seong Timmy Zhu William Muir ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/LICENSE0000644000076500000240000000206000000000000012527 0ustar00djcstaffMIT License Copyright (c) 2020 Dirkjan Ochtman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/MANIFEST.in0000644000076500000240000000010700000000000013260 0ustar00djcstaffinclude AUTHORS include README.rst include test.py include tests/*.rn* ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1631176377.535621 rnc2rng-2.6.6/PKG-INFO0000644000076500000240000000550000000000000012621 0ustar00djcstaffMetadata-Version: 2.1 Name: rnc2rng Version: 2.6.6 Summary: RELAX NG Compact to regular syntax conversion library Home-page: https://github.com/djc/rnc2rng Author: David Mertz Maintainer: Dirkjan Ochtman Maintainer-email: dirkjan@ochtman.nl License: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Operating System :: OS Independent Classifier: License :: OSI Approved :: MIT License Classifier: Topic :: Text Processing :: Markup :: XML Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 License-File: LICENSE License-File: AUTHORS RELAX NG Compact to RELAX NG conversion library =============================================== .. image:: https://github.com/djc/rnc2rng/workflows/CI/badge.svg :target: https://github.com/djc/rnc2rng/actions?query=workflow%3ACI .. image:: https://coveralls.io/repos/djc/rnc2rng/badge.svg?branch=master&service=github :target: https://coveralls.io/github/djc/rnc2rng?branch=master Converts RELAX NG schemata in Compact syntax (`rnc`) to the equivalent schema in the XML-based default RELAX NG syntax. Dependencies: - Python 3.x (tested with 3.7, 3.8, 3.9) - `rply`_ Feedback welcome on `GitHub`_. Please consider funding continued maintenance of this project through `Patreon`_ or `GitHub Sponsors`_. .. _GitHub: https://github.com/djc/rnc2rng .. _rply: https://pypi.python.org/pypi/rply .. _Patreon: https://patreon.com/dochtman .. _GitHub Sponsors: https://github.com/sponsors/djc History ------- rnc2rng was originally written by `David Mertz`_ in 2003 and published as part of a collection of files around RELAX NG `on his site`_ into the Public Domain. `Hartmut Goebel`_ published it as a package on PyPI to make it easier to access. It was mirrored on GitHub by `Dustin J. Mitchell`_ in 2010 after he fixed some bugs. `Timmy Zhu`_ forked his repository and contributed further enhancements. Recently, I (Dirkjan Ochtman) was interested in playing with RELAX NG Compact and started making further updates. I asked Hartmut for maintainership on PyPI and received it. While I cannot promise many updates, I should be responsive to bug reports and (especially!) pull requests. .. _David Mertz: http://www.gnosis.cx/publish/ .. _on his site: http://www.gnosis.cx/download/relax/ .. _Hartmut Goebel: http://www.goebel-consult.de/ .. _Dustin J. Mitchell: http://code.v.igoro.us/ .. _Timmy Zhu: https://github.com/nattofriends How to install -------------- The usual should work: .. code-block:: shell $ sudo pip install . Getting started --------------- .. code-block:: shell $ python -m rnc2rng test.rnc > test.rng License ------- All of the code is released under MIT License. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176259.0 rnc2rng-2.6.6/README.rst0000644000076500000240000000407300000000000013217 0ustar00djcstaffRELAX NG Compact to RELAX NG conversion library =============================================== .. image:: https://github.com/djc/rnc2rng/workflows/CI/badge.svg :target: https://github.com/djc/rnc2rng/actions?query=workflow%3ACI .. image:: https://coveralls.io/repos/djc/rnc2rng/badge.svg?branch=master&service=github :target: https://coveralls.io/github/djc/rnc2rng?branch=master Converts RELAX NG schemata in Compact syntax (`rnc`) to the equivalent schema in the XML-based default RELAX NG syntax. Dependencies: - Python 3.x (tested with 3.7, 3.8, 3.9) - `rply`_ Feedback welcome on `GitHub`_. Please consider funding continued maintenance of this project through `Patreon`_ or `GitHub Sponsors`_. .. _GitHub: https://github.com/djc/rnc2rng .. _rply: https://pypi.python.org/pypi/rply .. _Patreon: https://patreon.com/dochtman .. _GitHub Sponsors: https://github.com/sponsors/djc History ------- rnc2rng was originally written by `David Mertz`_ in 2003 and published as part of a collection of files around RELAX NG `on his site`_ into the Public Domain. `Hartmut Goebel`_ published it as a package on PyPI to make it easier to access. It was mirrored on GitHub by `Dustin J. Mitchell`_ in 2010 after he fixed some bugs. `Timmy Zhu`_ forked his repository and contributed further enhancements. Recently, I (Dirkjan Ochtman) was interested in playing with RELAX NG Compact and started making further updates. I asked Hartmut for maintainership on PyPI and received it. While I cannot promise many updates, I should be responsive to bug reports and (especially!) pull requests. .. _David Mertz: http://www.gnosis.cx/publish/ .. _on his site: http://www.gnosis.cx/download/relax/ .. _Hartmut Goebel: http://www.goebel-consult.de/ .. _Dustin J. Mitchell: http://code.v.igoro.us/ .. _Timmy Zhu: https://github.com/nattofriends How to install -------------- The usual should work: .. code-block:: shell $ sudo pip install . Getting started --------------- .. code-block:: shell $ python -m rnc2rng test.rnc > test.rng License ------- All of the code is released under MIT License. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1631176377.5183184 rnc2rng-2.6.6/rnc2rng/0000755000076500000240000000000000000000000013077 5ustar00djcstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093824.0 rnc2rng-2.6.6/rnc2rng/__init__.py0000644000076500000240000000045400000000000015213 0ustar00djcstafffrom . import parser, serializer def load(f): return parser.parse(f=f) def loads(src): return parser.parse(src) def dump(root, f, indent=None): f.write(serializer.XMLSerializer(indent).toxml(root)) def dumps(root, indent=None): return serializer.XMLSerializer(indent).toxml(root) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/rnc2rng/__main__.py0000755000076500000240000000100000000000000015163 0ustar00djcstaff#!/usr/bin/env python from __future__ import print_function from . import parser, serializer import sys def main(): args = sys.argv[1:] input = open(args[0]) if len(args) > 0 else sys.stdin try: xml = serializer.XMLSerializer().toxml(parser.parse(f=input)) except parser.ParseError as e: print('parse error ' + e.msg) sys.exit(1) if len(args) > 1: open(sys.argv[2], 'w').write(xml + '\n') else: print(xml) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631175668.0 rnc2rng-2.6.6/rnc2rng/parser.py0000644000076500000240000004756300000000000014764 0ustar00djcstafffrom codecs import BOM_UTF16_BE, BOM_UTF16_LE from urllib.request import urlopen from urllib.parse import urljoin, urlparse import rply, sys, os KEYWORDS = set([ 'attribute', 'datatypes', 'default', 'div', 'element', 'empty', 'external', 'grammar', 'include', 'inherit', 'list', 'mixed', 'namespace', 'notAllowed', 'parent', 'start', 'string', 'text', 'token', ]) NCNAME = r'[A-Za-z_][\w.-]*' def lexer(): lg = rply.LexerGenerator() lg.add('LPAREN', r'\(') lg.add('RPAREN', r'\)') lg.add('LBRACE', r'{') lg.add('RBRACE', r'}') lg.add('LBRACKET', r'\[') lg.add('RBRACKET', r'\]') lg.add('COMBINE', r'\|=|&=') lg.add('EQUAL', r'=') lg.add('PIPE', r'[|]') lg.add('COMMA', r',') lg.add('AMP', r'&') lg.add('MINUS', r'[-]') lg.add('STAR', r'[*]') lg.add('PLUS', r'[+]') lg.add('QMARK', r'[?]') lg.add('CNAME', r'%s:(%s|\*)' % (NCNAME, NCNAME)) lg.add('QID', r'\\%s' % NCNAME) lg.add('ID', NCNAME) lg.add('LITERAL', r'".*?"') lg.add('DOCUMENTATION', r'##.*') lg.add('COMMENT', r'#.*') lg.add('TILDE', r'~') lg.ignore(r'\s+') return lg.build() LEXER = lexer() def lex(src): for t in LEXER.lex(src): if t.name == 'ID' and t.value in KEYWORDS: t.name = t.value.upper() elif t.name == 'LITERAL': t.value = t.value[1:-1] elif t.name == 'COMMENT': continue yield t pg = rply.ParserGenerator([ 'AMP', 'CNAME', 'COMBINE', 'COMMA', 'DOCUMENTATION', 'EQUAL', 'ID', 'LBRACE', 'LBRACKET', 'LPAREN', 'LIST', 'LITERAL', 'MINUS', 'MIXED', 'PLUS', 'PIPE', 'QID', 'QMARK', 'RBRACE', 'RBRACKET', 'RPAREN', 'STAR', 'TILDE', ] + [s.upper() for s in KEYWORDS], precedence=[("left", ['TILDE'])]) class Node(object): __slots__ = 'type', 'name', 'value' def __init__(self, type, name, value=None): self.type = type self.name = name self.value = value or [] assert isinstance(self.value, list), self.value def __repr__(self): bits = [(k, getattr(self, k, None)) for k in self.__slots__] strs = ['%s=%r' % (k, v) for (k, v) in bits if v is not None] return 'Node(%s)' % ', '.join(strs) def pprint(n, level=0): if isinstance(n, list): print('[') for v in n: pprint(v, level + 2) print('%s]' % (' ' * level)) else: print('%s%s' % (' ' * level, n.type), end=' ') if n.name is not None: print(n.name, end=' ') if not n.value: print('[]') else: pprint(n.value, level) NODE_TYPES = [ 'ANNO_ATTR', 'ANNOTATION', 'ANY', 'ASSIGN', 'ATTR', 'CHOICE', 'DATATAG', 'DATATYPES', 'DEFAULT_NS', 'DEFINE', 'DIV', 'DOCUMENTATION', 'ELEM', 'EMPTY', 'EXCEPT', 'GRAMMAR', 'GROUP', 'INTERLEAVE', 'LIST', 'LITERAL', 'MAYBE', 'MIXED', 'NAME', 'NOT_ALLOWED', 'NS', 'PARAM', 'PARENT', 'REF', 'ROOT', 'SEQ', 'SOME', 'TEXT', ] for _node_type in NODE_TYPES: globals()[_node_type] = _node_type @pg.production('start : preamble top-level-body') def start(s, p): return Node('ROOT', None, p[0] + p[1]) @pg.production('strlit : LITERAL') def strlit_literal(s, p): # from datatypeValue return p[0] @pg.production('strlit : strlit TILDE strlit') def strlit_concat(s, p): p[0].value += p[2].value return p[0] @pg.production('preamble : decl preamble') def preamble_multi(s, p): p[1].insert(0, p[0]) return p[1] @pg.production('preamble : ') def preamble_empty(s, p): return [] @pg.production('decl : DEFAULT NAMESPACE EQUAL strlit') def decl_default_ns(s, p): return Node('DEFAULT_NS', None, [p[3].value.strip('"')]) @pg.production('decl : DEFAULT NAMESPACE id-or-kw EQUAL strlit') def decl_default_names_ns(s, p): return Node('DEFAULT_NS', p[2].name, [p[4].value.strip(' "')]) @pg.production('decl : NAMESPACE id-or-kw EQUAL strlit') def decl_ns(s, p): return Node('NS', p[1].name, [p[3].value.strip(' "')]) @pg.production('decl : DATATYPES id-or-kw EQUAL strlit') def decl_datatypes(s, p): return Node('DATATYPES', p[1].name, [p[3].value.strip('"')]) @pg.production('top-level-body : alt-top-level') def top_level_body(s, p): if isinstance(p[0], list): return p[0] elif p[0].type == 'ELEM': return [Node('DEFINE', 'start', [Node('ASSIGN', '=', [p[0]])])] elif p[0].type == 'GRAMMAR': return [p[0]] @pg.production('alt-top-level : grammar-content') def top_level_grammar_content(s, p): return p[0] @pg.production('alt-top-level : annotations element-primary') def top_level_element(s, p): p[1].value = p[0] + p[1].value return p[1] @pg.production('alt-top-level : grammar') def top_level_grammar(s, p): return p[0] @pg.production('grammar-content : member grammar-content') def grammar_multi(s, p): p[1].insert(0, p[0]) return p[1] @pg.production('grammar-content : ') def grammar_empty(s, p): return [] @pg.production('member : annotations component') def member_annotated_component(s, p): p[1].value = p[0] + p[1].value return p[1] @pg.production('member : CNAME annotation-attributes-content') def member_foreign_element_annotation(s, p): return Node('ANNOTATION', p[0].value, p[1]) @pg.production('component : define') def component_define(s, p): return p[0] @pg.production('component : grammar-start') def component_start(s, p): return p[0] @pg.production('define : identifier definition') def define(s, p): return Node('DEFINE', p[0].name, [p[1]]) @pg.production('grammar-start : START definition') def grammar_start(s, p): return Node('DEFINE', 'start', [p[1]]) @pg.production('definition : EQUAL pattern') def definition_equal(s, p): return Node('ASSIGN', p[0].value, p[1]) @pg.production('definition : COMBINE pattern') def definition_combine(s, p): return Node('ASSIGN', p[0].value, p[1]) @pg.production('component : DIV LBRACE grammar-content RBRACE') def component_div(s, p): return Node('DIV', None, p[2]) @pg.production('component : INCLUDE strlit opt-inherit opt-include-content') def component_include(s, p): if is_url(s.path) or is_url(p[1].value): # it's a URL url = urljoin(s.path, p[1].value) else: url = os.path.join(s.path, p[1].value) return parse(f=url) @pg.production('opt-inherit : INHERIT EQUAL id-or-kw') def opt_inherit(s, p): return Node('INHERIT', p[2]) @pg.production('opt-inherit : ') def opt_inherit_none(s, p): return None @pg.production('opt-include-content : LBRACE include-body RBRACE') def opt_include_content(s, p): return p[1] @pg.production('opt-include-content : ') def opt_include_content_none(s, p): return [] @pg.production('include-body : include-member include-body') def include_content_multi(s, p): p[1].insert(0, p[0]) return p[1] @pg.production('include-body : ') def include_content_empty(s, p): return [] @pg.production('include-member : annotations include-component') def include_member(s, p): p[1].value = p[0] + p[1].value return p[1] @pg.production('include-component : define') def include_component_define(s, p): return p[0] @pg.production('include-component : grammar-start') def include_component_start(s, p): return p[0] @pg.production('include-component : DIV LBRACE include-body RBRACE') def include_component_div(s, p): return Node('DIV', None, p[2]) @pg.production('annotation-attributes-content : LBRACKET start-annotation-content RBRACKET') def annotation_attributes_content(s, p): return p[1] @pg.production('annotations : documentations LBRACKET start-annotations RBRACKET') def annotations_multi(s, p): p[0] += p[2] return p[0] @pg.production('annotations : documentations') def annotations_empty(s, p): return p[0] @pg.production('start-annotation-content : CNAME cname-annotation-content') def start_annotation_content_cname(s, p): p[1][0].name = p[0].value return p[1] @pg.production('start-annotation-content : ID EQUAL strlit start-annotation-content') def start_annotation_content_id(s, p): return [Node('ANNO_ATTR', p[0].value, [p[2].value])] + p[3] @pg.production('start-annotation-content : strlit annotation-content') def start_annotation_content_literal(s, p): return [Node('LITERAL', p[0].value)] + p[1] @pg.production('start-annotation-content : ') def start_annotation_content_empty(s, p): return [] @pg.production('cname-annotation-content : EQUAL strlit start-annotation-content') def cname_annotation_content_attribute(s, p): return [Node('ANNO_ATTR', None, [p[1].value])] + p[2] @pg.production('cname-annotation-content : annotation-attributes-content annotation-content') def cname_annotation_content_element(s, p): return [Node('ANNOTATION', None, p[0])] + p[1] @pg.production('start-annotations : CNAME cname-annotations') def start_annotations_cname(s, p): p[1][0].name = p[0].value return p[1] @pg.production('start-annotations : ') def start_annotations_empty(s, p): return [] @pg.production('cname-annotations : EQUAL strlit start-annotations') def cname_annotations_attrib(s, p): return [Node('ANNO_ATTR', None, [p[1].value])] + p[2] @pg.production('cname-annotations : annotation-attributes-content annotation-elements') def cname_annotations_element(s, p): return [Node('ANNOTATION', None, p[0])] + p[1] @pg.production('annotation-content : annotation-element annotation-content') def annotation_content_nested(s, p): return [p[0]] + p[1] @pg.production('annotation-content : strlit annotation-content') def annotation_content_literal(s, p): return [Node('LITERAL', p[0].value)] + p[1] @pg.production('annotation-content : ') def annotation_content_empty(s, p): return [] @pg.production('annotation-elements : annotation-element annotation-elements') def annotation_elements_multi(s, p): p[1].insert(0, p[0]) return p[1] @pg.production('annotation-elements : ') def annotation_elements_empty(s, p): return [] @pg.production('annotation-element : CNAME annotation-attributes-content') def nested_annotation_element(s, p): return Node('ANNOTATION', p[0].value, p[1]) @pg.production('pattern : particle') def pattern_particle(s, p): return [p[0]] @pg.production('pattern : particle-choice') def pattern_choice(s, p): return [p[0]] @pg.production('particle-choice : particle PIPE particle-choice') def particle_choice_multi(s, p): p[2].value.insert(0, p[0]) return p[2] @pg.production('particle-choice : particle PIPE particle') def particle_choice_single(s, p): return Node('CHOICE', None, [p[0], p[2]]) @pg.production('pattern : particle-group') def pattern_seq(s, p): return [p[0]] @pg.production('particle-group : particle COMMA particle-group') def particle_group_multi(s, p): p[2].value.insert(0, p[0]) return p[2] @pg.production('particle-group : particle COMMA particle') def particle_group_single(s, p): return Node('SEQ', None, [p[0], p[2]]) @pg.production('pattern : particle-interleave') def pattern_interleave(s, p): return [p[0]] @pg.production('particle-interleave : particle AMP particle-interleave') def particle_interleave_multi(s, p): p[2].value.insert(0, p[0]) return p[2] @pg.production('particle-interleave : particle AMP particle') def particle_interleave_single(s, p): return Node('INTERLEAVE', None, [p[0], p[2]]) @pg.production('particle : annotated-primary QMARK') def particle_maybe(s, p): return Node('MAYBE', None, [p[0]]) @pg.production('particle : annotated-primary STAR') def particle_any(s, p): return Node('ANY', None, [p[0]]) @pg.production('particle : annotated-primary PLUS') def particle_some(s, p): return Node('SOME', None, [p[0]]) @pg.production('particle : annotated-primary') def particle_primary(s, p): return p[0] @pg.production('annotated-primary : LPAREN pattern RPAREN') def annotated_primary_group(s, p): return Node('GROUP', None, p[1]) @pg.production('annotated-primary : annotations primary') def annotated_primary_annotated(s, p): p[1].value = p[0] + p[1].value return p[1] @pg.production('primary : element-primary') def primary_element(s, p): return p[0] @pg.production('element-primary : ELEMENT name-class LBRACE pattern RBRACE') def element_primary(s, p): return Node('ELEM', None, p[1] + p[3]) @pg.production('primary : ATTRIBUTE name-class LBRACE pattern RBRACE') def primary_attrib(s, p): return Node('ATTR', None, p[1] + p[3]) @pg.production('primary : MIXED LBRACE pattern RBRACE') def primary_mixed(s, p): return Node('MIXED', None, p[2]) @pg.production('primary : LIST LBRACE pattern RBRACE') def primary_list(s, p): return Node('LIST', None, p[2]) @pg.production('primary : strlit') def primary_literal(s, p): # from datatypeValue return Node('LITERAL', p[0].value) @pg.production('primary : CNAME') def primary_cname(s, p): return Node('DATATAG', p[0].value.split(':', 1)[1]) @pg.production('primary : CNAME LBRACE params RBRACE') def primary_type_params(s, p): return Node('DATATAG', p[0].value, p[2]) @pg.production('primary : STRING') def primary_string(s, p): return Node('DATATAG', 'string') @pg.production('primary : STRING strlit') def primary_typed_string(s, p): return Node('DATATAG', 'string', [p[1].value]) @pg.production('primary : STRING LBRACE params RBRACE') def primary_string_parametrized(s, p): return Node('DATATAG', 'string', p[2]) @pg.production('primary : TEXT') def primary_text(s, p): return Node('TEXT', None) @pg.production('primary : EMPTY') def primary_empty(s, p): return Node('EMPTY', None) @pg.production('primary : identifier') def primary_id(s, p): return Node('REF', p[0].name) @pg.production('primary : NOTALLOWED') def primary_notallowed(s, p): return Node('NOT_ALLOWED', None) @pg.production('primary : PARENT ID') def primary_parent(s, p): return Node('PARENT', p[1].value) @pg.production('primary : grammar') def primary_grammar(s, p): return p[0] @pg.production('grammar : GRAMMAR LBRACE grammar-content RBRACE') def grammar(s, p): return Node('GRAMMAR', None, p[2]) @pg.production('params : params param') def params_multi(s, p): p[0].append(p[1]) return p[0] @pg.production('params : ') def params_empty(s, p): return [] @pg.production('param : id-or-kw EQUAL strlit') def param_single(s, p): return Node('PARAM', p[0].name, [p[2].value]) @pg.production('name-class : simple-name-class') def name_class_name(s, p): return p[0] @pg.production('name-class : name-class-choice') def name_class_choice(s, p): return p[0] @pg.production('name-class : except-name-class') def name_class_except(s, p): return p[0] @pg.production('except-name-class : simple-name-class MINUS except-name-class') def except_name_class_nested(s, p): p[0].value = p[2] return p[0] @pg.production('except-name-class : simple-name-class MINUS simple-name-class') def except_name_class_simple(s, p): p[0][0].value = [Node('EXCEPT', None, p[2])] return p[0] @pg.production('name-class-choice : simple-name-class PIPE name-class-choice') def name_class_choice_nested(s, p): p[2][0].value.insert(0, p[0][0]) return p[2] @pg.production('name-class-choice : simple-name-class PIPE simple-name-class') def name_class_choice_simple(s, p): return [Node('CHOICE', None, p[0] + p[2])] @pg.production('simple-name-class : STAR') def simple_name_class_any(s, p): return [Node('NAME', p[0].value)] @pg.production('simple-name-class : name') def simple_name_class_name(s, p): return [p[0]] @pg.production('simple-name-class : LPAREN name-class RPAREN') def name_class_group(s, p): return p[1] @pg.production('documentations : DOCUMENTATION documentations') def documentations_multi(s, p): cur = Node('DOCUMENTATION', None, []) if not p[1] else p[1][0] cur.value.insert(0, p[0].value.lstrip('# ').rstrip('\r')) return [cur] @pg.production('documentations : ') def documentations_empty(s, p): return [] @pg.production('name : CNAME') def name_cname(s, p): return Node('NAME', p[0].value) @pg.production('name : id-or-kw') def name_id(s, p): return p[0] @pg.production('id-or-kw : identifier') def id_or_kw_identifier(s, p): return p[0] @pg.production('id-or-kw : keyword') def id_or_kw_keyword(s, p): return p[0] @pg.production('identifier : ID') def id_kw_id(s, p): return Node('NAME', p[0].value) @pg.production('identifier : QID') def id_kw_quoted_identifier(s, p): return Node('NAME', p[0].value[1:]) @pg.production('keyword : ATTRIBUTE') def keyword_attr(s, p): return Node('NAME', p[0].value) @pg.production('keyword : DATATYPES') def keyword_dtypes(s, p): return Node('NAME', p[0].value) @pg.production('keyword : DEFAULT') def keyword_default(s, p): return Node('NAME', p[0].value) @pg.production('keyword : DIV') def keyword_div(s, p): return Node('NAME', p[0].value) @pg.production('keyword : ELEMENT') def keyword_elem(s, p): return Node('NAME', p[0].value) @pg.production('keyword : EMPTY') def keyword_empty(s, p): return Node('NAME', p[0].value) @pg.production('keyword : EXTERNAL') def keyword_external(s, p): return Node('NAME', p[0].value) @pg.production('keyword : GRAMMAR') def keyword_grammar(s, p): return Node('NAME', p[0].value) @pg.production('keyword : INCLUDE') def keyword_include(s, p): return Node('NAME', p[0].value) @pg.production('keyword : INHERIT') def keyword_inherit(s, p): return Node('NAME', p[0].value) @pg.production('keyword : LIST') def keyword_list(s, p): return Node('NAME', p[0].value) @pg.production('keyword : MIXED') def keyword_mixed(s, p): return Node('NAME', p[0].value) @pg.production('keyword : NAMESPACE') def keyword_namespace(s, p): return Node('NAME', p[0].value) @pg.production('keyword : NOTALLOWED') def keyword_notallowed(s, p): return Node('NAME', p[0].value) @pg.production('keyword : PARENT') def keyword_parent(s, p): return Node('NAME', p[0].value) @pg.production('keyword : START') def keyword_start(s, p): return Node('NAME', p[0].value) @pg.production('keyword : STRING') def keyword_string(s, p): return Node('NAME', p[0].value) @pg.production('keyword : TEXT') def keyword_text(s, p): return Node('NAME', p[0].value) @pg.production('keyword : TOKEN') def keyword_token(s, p): return Node('NAME', p[0].value) class ParseError(Exception): def __init__(self, t, fn, ln, col, line): self.token = t self.location = fn, ln, col self.line = line fn = fn if fn is not None else '(unknown)' loc = 'in %s [%s:%s]' % (fn, ln + 1, col + 1) spaces = col + 3 * min(col, line.count('\t')) line = line.replace('\t', ' ' * 4).rstrip() self.msg = '\n'.join((loc, line, ' ' * spaces + '^')) Exception.__init__(self, self.msg) @pg.error def error(s, t): ln = t.source_pos.lineno - 1 if t.value and t.value[0] == '\n': ln -= 1 col = t.source_pos.colno - 1 line = s.lines[ln] if ln < len(s.lines) else '' raise ParseError(t, s.fn, ln, col, line) parser = pg.build() class State(object): def __init__(self, fn, src): self.fn = fn self.path = os.getcwd() if fn is not None: self.path = os.path.dirname(os.path.abspath(fn)) if not is_url(fn) else fn self.lines = src.splitlines() if sys.version_info[0] < 3: str_types = str, bytes, unicode # noqa: unicode not defined in Python 3 else: str_types = str, bytes def is_url(fn): parse_result = urlparse(fn) return parse_result.scheme in ('http', 'https', 'file') def parse(src=None, f=None): assert src is None or f is None if f is not None and isinstance(f, str_types): fn = f if is_url(fn): with urlopen(fn) as f: bytes = f.read() else: with open(fn, 'rb') as f: bytes = f.read() bom = bytes[:2] in {BOM_UTF16_BE, BOM_UTF16_LE} src = bytes.decode('utf-16' if bom else 'utf-8') elif f is not None: fn, src = f.name, f.read() else: # Caller only gave source code, no filename. fn = None return parser.parse(lex(src), state=State(fn, src)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/rnc2rng/rnctree.py0000644000076500000240000000060300000000000015112 0ustar00djcstaff#!/usr/bin/env python # Compatibility API for rnc2rng 1.0 from . import parser, serializer class Tree(object): def __init__(self, root): self.root = root def toxml(self): return serializer.XMLSerializer().toxml(self.root) def token_list(src): return parser.lex(src) def make_nodetree(tokens): return Tree(parser.parser.parse(tokens, parser.State())) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176074.0 rnc2rng-2.6.6/rnc2rng/serializer.py0000644000076500000240000002315000000000000015623 0ustar00djcstaff# Convert an RELAX NG compact syntax schema to a Node tree # This file released to the Public Domain by David Mertz from . import parser from rnc2rng.parser import ( ANNO_ATTR, ANNOTATION, ANY, ASSIGN, ATTR, CHOICE, DATATAG, DATATYPES, DEFAULT_NS, DEFINE, DIV, DOCUMENTATION, ELEM, EMPTY, EXCEPT, GRAMMAR, GROUP, INTERLEAVE, LIST, LITERAL, MAYBE, MIXED, NAME, NOT_ALLOWED, NS, PARAM, PARENT, REF, ROOT, SEQ, SOME, TEXT, ) import html QUANTS = {SOME: 'oneOrMore', MAYBE: 'optional', ANY: 'zeroOrMore'} TYPELIB_NS = 'http://www.w3.org/2001/XMLSchema-datatypes' NAMESPACES = { 'a': 'http://relaxng.org/ns/compatibility/annotations/1.0', 'xml': 'http://www.w3.org/XML/1998/namespace', } class XMLSerializer(object): def __init__(self, indent=None): self.indent = indent or ' ' self.reset() def reset(self): self.buf = [] self.needs = {} self.types = None self.ns = {} self.default = '' self.level = 0 def write(self, s): self.buf.append(self.indent * self.level + s) def namespace(self, ns): assert ns in self.ns or ns in NAMESPACES, ns if ns not in self.ns: self.ns[ns] = NAMESPACES[ns] return self.ns[ns] def toxml(self, node): self.reset() types = None for n in node.value: if n.type == DATATYPES: types = n.value[0] self.types = types elif n.type == DEFAULT_NS: self.default = n.value[0] if n.name is not None: self.ns[n.name] = n.value[0] elif n.type == NS: self.ns[n.name] = n.value[0] prelude = [''] prelude.append('' self.write('') return '\n'.join(prelude + self.buf) def anno_attrs(self, nodes): select = lambda n: isinstance(n, parser.Node) and n.type == ANNO_ATTR pairs = [(n.name, html.escape(n.value[0])) for n in nodes if select(n)] if not pairs: return '' return ' ' + ' '.join('%s="%s"' % attr for attr in pairs) def visit(self, nodes, ctx=None, indent=True): '''Visiting a list of nodes, writes out the XML content to the internal line-based buffer. By default, adds one level of indentation to the output compared to the caller's level; passing False as the second argument will prevent this from happening.''' if indent: self.level += 1 for x in nodes: if not isinstance(x, parser.Node): raise TypeError("Not a Node: " + repr(x)) elif x.type in set([ANNO_ATTR, DATATYPES, DEFAULT_NS, NS]): continue attribs = self.anno_attrs(x.value) if x.type == DEFINE: op, attrib = x.value[0].name, '' if op in set(['|=', '&=']): modes = {'|': 'choice', '&': 'interleave'} attrib = ' combine="%s"' % modes[op[0]] if x.name == 'start': self.write('' % (attrib, attribs)) else: bits = x.name, attrib, attribs self.write('' % bits) self.visit(x.value) if x.name == 'start': self.write('') else: self.write('') elif x.type == ASSIGN: self.visit(x.value, indent=False) elif x.type == GRAMMAR: self.write('') self.visit(x.value) self.write('') elif x.type in set([MAYBE, SOME, ANY]): self.write('<%s>' % QUANTS[x.type]) self.visit(x.value) self.write('' % QUANTS[x.type]) elif x.type in set([INTERLEAVE, CHOICE, MIXED, LIST, DIV]): self.write('<%s>' % x.type.lower()) self.visit(x.value) self.write('' % x.type.lower()) elif x.type == EXCEPT: self.write('') self.visit(x.value, ctx=ctx) self.write('') elif x.type == NAME: if not x.value and '*' in x.name: if x.name == '*': self.write('') else: uri = self.ns[x.name.split(':', 1)[0]] self.write('' % uri) elif x.value: if x.name == '*': self.write('') else: uri = self.ns[x.name.split(':', 1)[0]] self.write('' % uri) self.visit(x.value, ctx=ctx) if x.name == '*': self.write('') else: self.write('') else: ns = '' if ctx == 'ATTR' else self.default name = x.name if ':' in name: parts = x.name.split(':', 1) ns = self.namespace(parts[0]) name = parts[1] self.write('%s' % (ns, name)) elif x.type in set([REF, PARENT]): bits = x.type.lower(), x.name, attribs self.write('<%s name="%s"%s/>' % bits) elif x.type == LITERAL: bits = attribs, html.escape(x.name) self.write('%s' % bits) self.visit(x.value, indent=False) elif x.type == ANNOTATION: literals, rest = [], [] for n in x.value: if n.type == LITERAL: literals.append(n.name) elif n.type != ANNO_ATTR: rest.append(n) end = '/' if not (literals or rest) else '' tail = '' if literals and not rest: tail = html.escape(''.join(literals)) + '' % x.name bits = x.name, attribs, end, tail self.write('<%s%s%s>%s' % bits) if not rest: continue for n in x.value: if n.type == ANNO_ATTR: continue elif n.type == LITERAL: self.level += 1 self.write(html.escape(n.name)) self.level -= 1 else: self.visit([n]) self.write('' % x.name) elif x.type == DOCUMENTATION: self.namespace('a') fmt = '%s' self.write(fmt % html.escape('\n'.join(x.value))) elif x.type == GROUP: if len(x.value) == 1 and x.value[0].type != SEQ: self.visit(x.value, indent=False) else: self.write('<%s>' % x.type.lower()) self.visit(x.value) self.write('' % x.type.lower()) elif x.type == NOT_ALLOWED: self.write('') elif x.type in set([TEXT, EMPTY]): self.write('<%s/>' % x.type.lower()) elif x.type == SEQ: self.visit(x.value, indent=False) elif x.type == DATATAG: self.needs['types'] = True if not x.value: # no parameters self.write('' % x.name) else: name = x.name if name not in ('string', 'token'): name = x.name.split(':', 1)[1] self.write('' % name) self.visit(x.value) self.write('') elif x.type == PARAM: bits = x.name, html.escape(x.value[0]) self.write('%s' % bits) elif x.type == ELEM: self.write('' % attribs) self.visit(x.value) self.write('') elif x.type == ATTR: self.write('' % attribs) self.visit(x.value, ctx=x.type) self.write('') elif x.type == ROOT: # Verify the included document has the same metadata for n in x.value: if n.type == DATATYPES: assert self.types == n.value[0] elif n.type == DEFAULT_NS: assert self.default == n.value[0] elif n.type == NS: assert n.name in self.ns assert self.ns[n.name] == n.value[0] self.visit(x.value, indent=False) else: assert False, x if indent: self.level -= 1 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1631176377.5206728 rnc2rng-2.6.6/rnc2rng.egg-info/0000755000076500000240000000000000000000000014571 5ustar00djcstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176377.0 rnc2rng-2.6.6/rnc2rng.egg-info/PKG-INFO0000644000076500000240000000550000000000000015666 0ustar00djcstaffMetadata-Version: 2.1 Name: rnc2rng Version: 2.6.6 Summary: RELAX NG Compact to regular syntax conversion library Home-page: https://github.com/djc/rnc2rng Author: David Mertz Maintainer: Dirkjan Ochtman Maintainer-email: dirkjan@ochtman.nl License: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Operating System :: OS Independent Classifier: License :: OSI Approved :: MIT License Classifier: Topic :: Text Processing :: Markup :: XML Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 License-File: LICENSE License-File: AUTHORS RELAX NG Compact to RELAX NG conversion library =============================================== .. image:: https://github.com/djc/rnc2rng/workflows/CI/badge.svg :target: https://github.com/djc/rnc2rng/actions?query=workflow%3ACI .. image:: https://coveralls.io/repos/djc/rnc2rng/badge.svg?branch=master&service=github :target: https://coveralls.io/github/djc/rnc2rng?branch=master Converts RELAX NG schemata in Compact syntax (`rnc`) to the equivalent schema in the XML-based default RELAX NG syntax. Dependencies: - Python 3.x (tested with 3.7, 3.8, 3.9) - `rply`_ Feedback welcome on `GitHub`_. Please consider funding continued maintenance of this project through `Patreon`_ or `GitHub Sponsors`_. .. _GitHub: https://github.com/djc/rnc2rng .. _rply: https://pypi.python.org/pypi/rply .. _Patreon: https://patreon.com/dochtman .. _GitHub Sponsors: https://github.com/sponsors/djc History ------- rnc2rng was originally written by `David Mertz`_ in 2003 and published as part of a collection of files around RELAX NG `on his site`_ into the Public Domain. `Hartmut Goebel`_ published it as a package on PyPI to make it easier to access. It was mirrored on GitHub by `Dustin J. Mitchell`_ in 2010 after he fixed some bugs. `Timmy Zhu`_ forked his repository and contributed further enhancements. Recently, I (Dirkjan Ochtman) was interested in playing with RELAX NG Compact and started making further updates. I asked Hartmut for maintainership on PyPI and received it. While I cannot promise many updates, I should be responsive to bug reports and (especially!) pull requests. .. _David Mertz: http://www.gnosis.cx/publish/ .. _on his site: http://www.gnosis.cx/download/relax/ .. _Hartmut Goebel: http://www.goebel-consult.de/ .. _Dustin J. Mitchell: http://code.v.igoro.us/ .. _Timmy Zhu: https://github.com/nattofriends How to install -------------- The usual should work: .. code-block:: shell $ sudo pip install . Getting started --------------- .. code-block:: shell $ python -m rnc2rng test.rnc > test.rng License ------- All of the code is released under MIT License. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176377.0 rnc2rng-2.6.6/rnc2rng.egg-info/SOURCES.txt0000644000076500000240000000225700000000000016463 0ustar00djcstaffAUTHORS LICENSE MANIFEST.in README.rst setup.cfg setup.py test.py rnc2rng/__init__.py rnc2rng/__main__.py rnc2rng/parser.py rnc2rng/rnctree.py rnc2rng/serializer.py rnc2rng.egg-info/PKG-INFO rnc2rng.egg-info/SOURCES.txt rnc2rng.egg-info/dependency_links.txt rnc2rng.egg-info/entry_points.txt rnc2rng.egg-info/requires.txt rnc2rng.egg-info/top_level.txt tests/annotations.rnc tests/annotations.rng tests/attr-no-default-ns.rnc tests/attr-no-default-ns.rng tests/datatypes.rnc tests/datatypes.rng tests/default-ns.rnc tests/default-ns.rng tests/documentation.rnc tests/documentation.rng tests/encoding.rng tests/encoding_utf16be.rnc tests/encoding_utf16be.rng tests/encoding_utf16le.rnc tests/encoding_utf16le.rng tests/encoding_utf8.rnc tests/encoding_utf8.rng tests/features.rnc tests/features.rng tests/include.rnc tests/include.rng tests/ns-concat.rnc tests/ns-concat.rng tests/ns.rnc tests/ns.rng tests/qid.rnc tests/qid.rng tests/relax.rnc tests/relax.rng tests/simple-escape.rnc tests/simple-escape.rng tests/simple.rnc tests/simple.rng tests/spec-6.1-1.rnc tests/spec-6.1-1.rng tests/spec-6.1-2.rnc tests/spec-6.1-2.rng tests/svn.rnc tests/svn.rng tests/type-pattern.rnc tests/type-pattern.rng././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176377.0 rnc2rng-2.6.6/rnc2rng.egg-info/dependency_links.txt0000644000076500000240000000000100000000000020637 0ustar00djcstaff ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176377.0 rnc2rng-2.6.6/rnc2rng.egg-info/entry_points.txt0000644000076500000240000000006300000000000020066 0ustar00djcstaff[console_scripts] rnc2rng = rnc2rng.__main__:main ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176377.0 rnc2rng-2.6.6/rnc2rng.egg-info/requires.txt0000644000076500000240000000000500000000000017164 0ustar00djcstaffrply ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176377.0 rnc2rng-2.6.6/rnc2rng.egg-info/top_level.txt0000644000076500000240000000001000000000000017312 0ustar00djcstaffrnc2rng ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1631176377.5361154 rnc2rng-2.6.6/setup.cfg0000644000076500000240000000015400000000000013345 0ustar00djcstaff[flake8] ignore = E261,E301,E302,E305,E401,E731 max_line_length = 99 [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1631176224.0 rnc2rng-2.6.6/setup.py0000644000076500000240000000172600000000000013244 0ustar00djcstafffrom setuptools import setup setup( name='rnc2rng', version='2.6.6', url='https://github.com/djc/rnc2rng', author='David Mertz', description='RELAX NG Compact to regular syntax conversion library', long_description=open('README.rst').read(), maintainer='Dirkjan Ochtman', maintainer_email='dirkjan@ochtman.nl', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Operating System :: OS Independent', 'License :: OSI Approved :: MIT License', 'Topic :: Text Processing :: Markup :: XML', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', ], packages=['rnc2rng'], entry_points={ 'console_scripts': [ 'rnc2rng = rnc2rng.__main__:main', ], }, install_requires=['rply'], ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/test.py0000644000076500000240000000370500000000000013062 0ustar00djcstaffimport rnc2rng import unittest, os import sys if sys.version_info[0] < 3: from urllib import pathname2url, url2pathname from urlparse import urljoin, urlparse else: from urllib.parse import urljoin, urlparse from urllib.request import pathname2url, url2pathname class TestUtils(unittest.TestCase): def assertBestEqual(self, expected, actual): if hasattr(self, 'assertMultiLineEqual'): self.assertMultiLineEqual(expected, actual) else: self.assertEqual(expected, actual) class FileTest(TestUtils): def __init__(self, fn): unittest.TestCase.__init__(self) self.fn = fn self.maxDiff = None def __str__(self): return 'TestCase(%r)' % self.fn def runTest(self): root = rnc2rng.load(self.fn) ref = self.fn.replace('.rnc', '.rng') if ref.startswith('file:'): parse_result = urlparse(ref) ref = url2pathname(parse_result.path) with open(ref) as f: expected = f.read().rstrip() actual = rnc2rng.dumps(root).strip() self.assertBestEqual(expected, actual) class APITests(TestUtils): def test_from_string(self): with open('tests/features.rnc') as f: src = f.read() with open('tests/features.rng') as f: expected = f.read().rstrip() actual = rnc2rng.dumps(rnc2rng.loads(src)).strip() self.assertBestEqual(expected, actual) def suite(): suite = unittest.TestLoader().loadTestsFromTestCase(APITests) for fn in os.listdir('tests'): if not fn.endswith('.rnc'): continue fn = os.path.join('tests', fn) suite.addTest(FileTest(fn)) # synthesize a test that reads its input from a URL url_test_path = os.path.abspath('tests/include.rnc') suite.addTest(FileTest(urljoin('file:', pathname2url(url_test_path)))) return suite if __name__ == '__main__': unittest.main(defaultTest='suite') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1631176377.5352755 rnc2rng-2.6.6/tests/0000755000076500000240000000000000000000000012666 5ustar00djcstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/annotations.rnc0000644000076500000240000000164200000000000015732 0ustar00djcstaffnamespace x = "http://www.example.com" namespace dc = "http://purl.org/dc/elements/1.1/" namespace sch = "http://www.ascc.net/xml/schematron" x:entity [ name="picture" systemId="picture.jpg" notation="jpg" ] dc:title [ "Foo without contents & escaped" ] sch:ns [ uri = "http://purl.org/dc/elements/1.1" prefix = "dc" ] sch:pattern [ name = "Some thing & other" sch:rule [ context = "//foo" sch:assert [ test = "@bar = /@bar" "attrib matches top-level attribute" ] ] sch:rule [ context = "//barfoo" sch:assert [ test = "@quick = @fast" "tautology of speediness" ] ] "one literal & next:" "two literal" ] [ a:documentation [ dc:title [ "schema starts here" ] ] ] div { foo = element foo { [ a:defaultValue = "1.0" ] attribute version { "1.0" } } } start = foo ## documentation for definition ## continues on the next line bar = element bar { empty } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/annotations.rng0000644000076500000240000000266700000000000015746 0ustar00djcstaff Foo without contents & escaped attrib matches top-level attribute tautology of speediness one literal & next: two literal
schema starts here foo version 1.0
documentation for definition continues on the next line bar
././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/attr-no-default-ns.rnc0000644000076500000240000000014100000000000017012 0ustar00djcstaffdefault namespace = "https://namespace.com" MyEl = element elem { attribute * - utils { text } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/attr-no-default-ns.rng0000644000076500000240000000064500000000000017027 0ustar00djcstaff elem utils ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/datatypes.rnc0000644000076500000240000000013300000000000015365 0ustar00djcstaffdatatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes" element height { xsd:double } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/datatypes.rng0000644000076500000240000000043400000000000015375 0ustar00djcstaff height ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/default-ns.rnc0000644000076500000240000000012200000000000015427 0ustar00djcstaffdefault namespace = "http://example.com" element foo { attribute bar { string } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/default-ns.rng0000644000076500000240000000062200000000000015440 0ustar00djcstaff foo bar ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/documentation.rnc0000644000076500000240000000012600000000000016242 0ustar00djcstaff## Represents a language element lang { ## English "en" | ## Japanese "jp" } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/documentation.rng0000644000076500000240000000077000000000000016253 0ustar00djcstaff Represents a language lang en English jp Japanese ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/encoding.rng0000644000076500000240000000030500000000000015162 0ustar00djcstaff foo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/encoding_utf16be.rnc0000644000076500000240000000011000000000000016504 0ustar00djcstaffþÿelement foo { text } # en-dash ( ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/encoding_utf16be.rng0000644000076500000240000000030500000000000016516 0ustar00djcstaff foo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/encoding_utf16le.rnc0000644000076500000240000000011000000000000016516 0ustar00djcstaffÿþelement foo { text } # en-dash ( ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/encoding_utf16le.rng0000644000076500000240000000030500000000000016530 0ustar00djcstaff foo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/encoding_utf8.rnc0000644000076500000240000000004500000000000016125 0ustar00djcstaffelement foo { text } # en-dash (–) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/encoding_utf8.rng0000644000076500000240000000030500000000000016130 0ustar00djcstaff foo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/features.rnc0000644000076500000240000000137600000000000015217 0ustar00djcstaffZ = element z { empty } Foo = "foo" start = element a { attribute b { "c" }, element d { Z }*, # e element f { "g & gg" }?, element h { (element i { empty } | element j { empty }) & (element k { xsd:integer { maxInclusive = "65535" } }) }+, element l { (attribute m { "n" } & attribute o { "p" | "q" } & attribute r { text }), attribute s { string { pattern = "t" } }, attribute t { parent Z }?, attribute u { Foo } }, element v { mixed { element w { empty }, element y { empty } }, list { element z { notAllowed } } } } div { start = element X { empty } start |= element Y { empty } Z &= element zz { empty } } aa = element aa { (attribute ab { empty }, attribute ac { empty }?) } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/features.rng0000644000076500000240000000655500000000000015227 0ustar00djcstaff z foo a b c d f g & gg h i j k 65535 l m n o p q r s t t u v w y z
X Y zz
aa ab ac
././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/include.rnc0000644000076500000240000000015200000000000015013 0ustar00djcstaffdatatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes" include "datatypes.rnc" include "simple.rnc" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/include.rng0000644000076500000240000000057100000000000015024 0ustar00djcstaff height foo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/ns-concat.rnc0000644000076500000240000000015500000000000015260 0ustar00djcstaffnamespace rng = "http://" ~ "relaxng.org/" ~ "ns/" ~ "structure/" ~ "1.0" element rng:text { empty } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/ns-concat.rng0000644000076500000240000000044300000000000015264 0ustar00djcstaff text ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/ns.rnc0000644000076500000240000000012100000000000014004 0ustar00djcstaffnamespace rng = "http://relaxng.org/ns/structure/1.0" element rng:text { empty } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/ns.rng0000644000076500000240000000044300000000000014017 0ustar00djcstaff text ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/qid.rnc0000644000076500000240000000012000000000000014140 0ustar00djcstaffdefault namespace = "http://example.com" foo = element bar { \baz } \baz = text ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/qid.rng0000644000076500000240000000047500000000000014161 0ustar00djcstaff bar ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/relax.rnc0000644000076500000240000000407600000000000014514 0ustar00djcstaff# RELAX NG XML syntax specified in compact syntax. default namespace rng = "http://relaxng.org/ns/structure/1.0" namespace local = "" datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes" start = pattern pattern = element element { (nameQName | nameClass), (common & pattern+) } | element attribute { (nameQName | nameClass), (common & pattern?) } | element group|interleave|choice|optional |zeroOrMore|oneOrMore|list|mixed { common & pattern+ } | element ref|parentRef { nameNCName, common } | element empty|notAllowed|text { common } | element data { type, param*, (common & exceptPattern?) } | element value { commonAttributes, type?, xsd:string } | element externalRef { href, common } | element grammar { common & grammarContent* } param = element param { commonAttributes, nameNCName, xsd:string } exceptPattern = element except { common & pattern+ } grammarContent = definition | element div { common & grammarContent* } | element include { href, (common & includeContent*) } includeContent = definition | element div { common & includeContent* } definition = element start { combine?, (common & pattern+) } | element define { nameNCName, combine?, (common & pattern+) } combine = attribute combine { "choice" | "interleave" } nameClass = element name { commonAttributes, xsd:QName } | element anyName { common & exceptNameClass? } | element nsName { common & exceptNameClass? } | element choice { common & nameClass+ } exceptNameClass = element except { common & nameClass+ } nameQName = attribute name { xsd:QName } nameNCName = attribute name { xsd:NCName } href = attribute href { xsd:anyURI } type = attribute type { xsd:NCName } common = commonAttributes, foreignElement* commonAttributes = attribute ns { xsd:string }?, attribute datatypeLibrary { xsd:anyURI }?, foreignAttribute* foreignElement = element * - rng:* { (anyAttribute | text | anyElement)* } foreignAttribute = attribute * - (rng:*|local:*) { text } anyElement = element * { (anyAttribute | text | anyElement)* } anyAttribute = attribute * { text } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/relax.rng0000644000076500000240000002224300000000000014514 0ustar00djcstaff element attribute group interleave choice optional zeroOrMore oneOrMore list mixed ref parentRef empty notAllowed text data value externalRef grammar param except div include div start define combine choice interleave name anyName nsName choice except name name href type ns datatypeLibrary ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/simple-escape.rnc0000644000076500000240000000004200000000000016115 0ustar00djcstaffelement string { text } # comment ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/simple-escape.rng0000644000076500000240000000031000000000000016117 0ustar00djcstaff string ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/simple.rnc0000644000076500000240000000003700000000000014663 0ustar00djcstaffelement foo { text } # comment ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/simple.rng0000644000076500000240000000030500000000000014665 0ustar00djcstaff foo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/spec-6.1-1.rnc0000644000076500000240000000003400000000000014761 0ustar00djcstaffstart = element * { empty } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/spec-6.1-1.rng0000644000076500000240000000027200000000000014771 0ustar00djcstaff ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/spec-6.1-2.rnc0000644000076500000240000000003200000000000014760 0ustar00djcstaffelement * - foo { empty } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/spec-6.1-2.rng0000644000076500000240000000041600000000000014772 0ustar00djcstaff foo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/svn.rnc0000644000076500000240000000067500000000000014210 0ustar00djcstaffnamespace xsd = "http://www.w3.org/2001/XMLSchema" grammar { start = element svn { # Path to the svn dump file attribute dump-file { xsd:string }?, # Content of the .SVNAccessFile inline in the XML (element access-file { xsd:string }? # E-mail subscriptions & element notification { attribute path { xsd:string }, attribute emails { xsd:string } }*) } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/svn.rng0000644000076500000240000000213300000000000014203 0ustar00djcstaff svn dump-file access-file notification path emails ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/type-pattern.rnc0000644000076500000240000000005600000000000016027 0ustar00djcstaffelement foo { string { pattern = "[abc]+" } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1607093380.0 rnc2rng-2.6.6/tests/type-pattern.rng0000644000076500000240000000052300000000000016032 0ustar00djcstaff foo [abc]+