forked from openlp/openlp
add openlyrics validator
This commit is contained in:
parent
d8642636ec
commit
15b63b8279
467
testing/resources/openlyrics/openlyrics_schema.rng
Normal file
467
testing/resources/openlyrics/openlyrics_schema.rng
Normal file
@ -0,0 +1,467 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
|
||||
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
|
||||
ns="http://openlyrics.info/namespace/2009/song">
|
||||
|
||||
<!-- TOP LEVEL -->
|
||||
|
||||
<start>
|
||||
<element name="song">
|
||||
<ref name="songAttributes"/>
|
||||
<ref name="properties"/>
|
||||
<optional>
|
||||
<ref name="format"/>
|
||||
</optional>
|
||||
<ref name="lyrics"/>
|
||||
</element>
|
||||
</start>
|
||||
|
||||
<define name="properties">
|
||||
<element name="properties">
|
||||
<interleave> <!-- allow occur in any order -->
|
||||
<!-- at least one title is always required -->
|
||||
<ref name="titles"/>
|
||||
<!-- other properties items are optional -->
|
||||
<optional>
|
||||
<ref name="authors"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="copyright"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="ccliNo"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="releaseDate"/>
|
||||
</optional>
|
||||
<!-- Music Info -->
|
||||
<optional>
|
||||
<ref name="transposition"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="tempo"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="key"/>
|
||||
</optional>
|
||||
<!-- Other Info -->
|
||||
<optional>
|
||||
<ref name="variant"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="publisher"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="customVersion"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="keywords"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="verseOrder"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="songbooks"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="themes"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="comments"/>
|
||||
</optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="format">
|
||||
<element name="format">
|
||||
<ref name="formatTags"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
|
||||
<define name="lyrics">
|
||||
<element name="lyrics">
|
||||
<!-- at least one verse is required -->
|
||||
<oneOrMore>
|
||||
<ref name="verse"/>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- PROPERTIES -->
|
||||
|
||||
<define name="titles">
|
||||
<element name="titles">
|
||||
<oneOrMore>
|
||||
<element name="title">
|
||||
<ref name="nonEmptyContent"/>
|
||||
<optional>
|
||||
<ref name="langAttribute"/>
|
||||
<optional>
|
||||
<ref name="translitAttribute"/>
|
||||
</optional>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="original">
|
||||
<data type="boolean"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- AUTHOR info -->
|
||||
|
||||
<define name="authors">
|
||||
<element name="authors">
|
||||
<oneOrMore>
|
||||
<element name="author">
|
||||
<ref name="nonEmptyContent"/>
|
||||
<optional>
|
||||
<choice>
|
||||
<attribute name="type">
|
||||
<choice>
|
||||
<value>words</value>
|
||||
<value>music</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<!-- when attrib 'type' value is 'translation' require attribute 'lang'.
|
||||
'xml:lang' can't be used. xml:lang means in what language is the
|
||||
content of an element and this is not the case. -->
|
||||
<group>
|
||||
<attribute name="type">
|
||||
<value>translation</value>
|
||||
</attribute>
|
||||
<ref name="langAttribute"/>
|
||||
</group>
|
||||
</choice>
|
||||
</optional>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="copyright">
|
||||
<element name="copyright">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="ccliNo">
|
||||
<element name="ccliNo">
|
||||
<data type="positiveInteger"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="releaseDate">
|
||||
<element name="releaseDate">
|
||||
<!-- allowed values
|
||||
1779
|
||||
1779-12
|
||||
1779-12-31
|
||||
1779-12-31T13:15:30+01:00 -->
|
||||
<choice>
|
||||
<data type="gYear"/>
|
||||
<data type="gYearMonth"/>
|
||||
<data type="date"/>
|
||||
<data type="dateTime"/>
|
||||
</choice>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- MUSIC INFO -->
|
||||
|
||||
<define name="transposition">
|
||||
<element name="transposition">
|
||||
<data type="integer">
|
||||
<param name="minInclusive">-99</param>
|
||||
<param name="maxInclusive">99</param>
|
||||
</data>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="tempo">
|
||||
<element name="tempo">
|
||||
<choice>
|
||||
<!-- attrib 'type' value 'bpm' - beatss per minute required -->
|
||||
<group>
|
||||
<data type="positiveInteger">
|
||||
<param name="minInclusive">30</param>
|
||||
<param name="maxInclusive">250</param>
|
||||
</data>
|
||||
<attribute name="type">
|
||||
<value>bpm</value>
|
||||
</attribute>
|
||||
</group>
|
||||
<!-- attrib 'type' value 'text' - any text -->
|
||||
<group>
|
||||
<ref name="nonEmptyContent"/>
|
||||
<attribute name="type">
|
||||
<value>text</value>
|
||||
</attribute>
|
||||
</group>
|
||||
</choice>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
|
||||
<define name="key">
|
||||
<element name="key">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- OTHER INFO -->
|
||||
|
||||
<define name="variant">
|
||||
<element name="variant">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="publisher">
|
||||
<element name="publisher">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="customVersion">
|
||||
<element name="customVersion">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="keywords">
|
||||
<element name="keywords">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="verseOrder">
|
||||
<element name="verseOrder">
|
||||
<list>
|
||||
<oneOrMore>
|
||||
<ref name="verseNameType"/>
|
||||
</oneOrMore>
|
||||
</list>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="songbooks">
|
||||
<element name="songbooks">
|
||||
<oneOrMore>
|
||||
<element name="songbook">
|
||||
<attribute name="name">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
<optional>
|
||||
<!-- 'entry' is like song number but song number must not
|
||||
always be integer and it can contain letters.
|
||||
examples: '153c' or '023', etc. -->
|
||||
<attribute name="entry">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="themes">
|
||||
<element name="themes">
|
||||
<oneOrMore>
|
||||
<element name="theme">
|
||||
<ref name="nonEmptyContent"/>
|
||||
<optional>
|
||||
<!-- id: line in a ccli theme list from
|
||||
http://www.ccli.com.au/owners/themes.cfm -->
|
||||
<attribute name="id">
|
||||
<data type="positiveInteger">
|
||||
<param name="minInclusive">1</param>
|
||||
<param name="maxInclusive">999</param>
|
||||
</data>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="langAttribute"/>
|
||||
<optional>
|
||||
<ref name="translitAttribute"/>
|
||||
</optional>
|
||||
</optional>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="comments">
|
||||
<element name="comments">
|
||||
<oneOrMore>
|
||||
<element name="comment">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- FORMAT -->
|
||||
|
||||
<define name="formatTags">
|
||||
<!-- Allow only one set of formatting tags for lyrics -->
|
||||
<element name="tags">
|
||||
<attribute name="application">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
<oneOrMore>
|
||||
<ref name="formatTagsTag"/>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="formatTagsTag">
|
||||
<element name="tag">
|
||||
<attribute name="name">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
<element name="open">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
<element name="close">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- LYRICS -->
|
||||
|
||||
<define name="verse">
|
||||
<element name="verse">
|
||||
<ref name="verseAttributes"/>
|
||||
<optional>
|
||||
<ref name="langAttribute"/>
|
||||
<optional>
|
||||
<ref name="translitAttribute"/>
|
||||
</optional>
|
||||
</optional>
|
||||
<oneOrMore>
|
||||
<ref name="lines"/>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="lines">
|
||||
<element name="lines">
|
||||
<optional>
|
||||
<attribute name="part">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="break">
|
||||
<value>optional</value>
|
||||
</attribute>
|
||||
</optional>
|
||||
<oneOrMore>
|
||||
<optional>
|
||||
<element name="comment">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</optional>
|
||||
<element name="line">
|
||||
<!-- allow tag chord inside regular text - mixed content -->
|
||||
<zeroOrMore>
|
||||
<optional>
|
||||
<ref name="chord"/>
|
||||
</optional>
|
||||
<!-- allow tag 'tag' inside regular text - mixed content -->
|
||||
<optional>
|
||||
<ref name="tag"/>
|
||||
</optional>
|
||||
<text/>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="chord">
|
||||
<element name="chord">
|
||||
<attribute name="name">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
<empty/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="tag">
|
||||
<element name="tag">
|
||||
<attribute name="name">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
<ref name="nonEmptyContent"/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="verseAttributes">
|
||||
<attribute name="name">
|
||||
<ref name="verseNameType"/>
|
||||
</attribute>
|
||||
</define>
|
||||
|
||||
<define name="songAttributes">
|
||||
<!-- by default: value of type string is required in attr -->
|
||||
<attribute name="version">
|
||||
<data type="NMTOKEN"> <!-- one word value -->
|
||||
<!-- allow only values like: '0.1' '11.2' '13.14.15' -->
|
||||
<param name="pattern">[0-9]+\.[0-9]+(\.[0-9]+)?</param>
|
||||
</data>
|
||||
</attribute>
|
||||
<attribute name="createdIn">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
<attribute name="modifiedIn">
|
||||
<ref name="nonEmptyContent"/>
|
||||
</attribute>
|
||||
<attribute name="modifiedDate">
|
||||
<!-- date format: ISO 8601 -->
|
||||
<data type="dateTime"/>
|
||||
</attribute>
|
||||
</define>
|
||||
|
||||
<define name="verseNameType">
|
||||
<choice>
|
||||
<data type="NMTOKEN">
|
||||
<param name="minLength">1</param>
|
||||
<!-- verse - v1, v2, v1a, ... 3 letters: [verse][verse_number][verse_part]
|
||||
chorus c, c1, c2, c1a, ca, ...
|
||||
pre-chorus - p, p1, p2, p1a, pa, ...
|
||||
bridge - b, b1, b2, b1a, ba, ...
|
||||
ending - e, e1, e2, e1a, ea, ... -->
|
||||
<param name="pattern">(v[1-9]\d?[a-z]?)|([cpb][a-z]?)|([cpbe][1-9]\d?[a-z]?)</param>
|
||||
</data>
|
||||
<!-- custom values of verse name - one word name -->
|
||||
<data type="NMTOKEN"/>
|
||||
</choice>
|
||||
</define>
|
||||
|
||||
<define name="langAttribute">
|
||||
<attribute name="lang">
|
||||
<data type="language"/>
|
||||
</attribute>
|
||||
</define>
|
||||
|
||||
<!-- transliteration -->
|
||||
<define name="translitAttribute">
|
||||
<attribute name="translit">
|
||||
<data type="language"/>
|
||||
</attribute>
|
||||
</define>
|
||||
|
||||
<define name="nonEmptyContent">
|
||||
<data type="string">
|
||||
<param name="minLength">1</param>
|
||||
</data>
|
||||
</define>
|
||||
|
||||
</grammar>
|
26
testing/resources/openlyrics/validate.py
Executable file
26
testing/resources/openlyrics/validate.py
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
from lxml import etree
|
||||
except ImportError:
|
||||
print('Python module "lxml" is required')
|
||||
exit(1)
|
||||
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
print('Usage: python %s openlyrics_schema.rng xmlfile.xml' % __file__)
|
||||
exit(1)
|
||||
|
||||
|
||||
relaxng_file = sys.argv[1]
|
||||
xml_file = sys.argv[2]
|
||||
|
||||
relaxng_doc = etree.parse(relaxng_file)
|
||||
xml_doc = etree.parse(xml_file)
|
||||
|
||||
relaxng = etree.RelaxNG(relaxng_doc)
|
||||
|
||||
relaxng.assertValid(xml_doc)
|
||||
|
Loading…
Reference in New Issue
Block a user