Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
django-opds/docs/validators/atom.rnc
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
263 lines (261 sloc)
6.42 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- rnc -*- | |
# RELAX NG Compact Syntax Grammar for the | |
# Atom Format Specification Version 11 | |
namespace atom = "http://www.w3.org/2005/Atom" | |
namespace local = "" | |
namespace s = "http://www.ascc.net/xml/schematron" | |
namespace xhtml = "http://www.w3.org/1999/xhtml" | |
start = atomFeed | atomEntry | |
# Common attributes | |
atomCommonAttributes = | |
attribute xml:base { atomUri }?, | |
attribute xml:lang { atomLanguageTag }?, | |
undefinedAttribute* | |
# Text Constructs | |
atomPlainTextConstruct = | |
atomCommonAttributes, | |
attribute type { "text" | "html" }?, | |
text | |
atomXHTMLTextConstruct = | |
atomCommonAttributes, | |
attribute type { "xhtml" }, | |
xhtmlDiv | |
atomTextConstruct = atomPlainTextConstruct | atomXHTMLTextConstruct | |
# Person Construct | |
atomPersonConstruct = | |
atomCommonAttributes, | |
(element atom:name { text } | |
& element atom:uri { atomUri }? | |
& element atom:email { atomEmailAddress }? | |
& extensionElement*) | |
# Date Construct | |
atomDateConstruct = atomCommonAttributes, xsd:dateTime | |
# atom:feed | |
atomFeed = | |
[ | |
s:rule [ | |
context = "atom:feed" | |
"\x{a}" ~ | |
" " | |
s:assert [ | |
test = "atom:author or not(atom:entry[not(atom:author)])" | |
"An atom:feed must have an atom:author unless all of its atom:entry children have an atom:author." | |
] | |
"\x{a}" ~ | |
" " | |
] | |
] | |
element atom:feed { | |
atomCommonAttributes, | |
(atomAuthor* | |
& atomCategory* | |
& atomContributor* | |
& atomGenerator? | |
& atomIcon? | |
& atomId | |
& atomLink* | |
& atomLogo? | |
& atomRights? | |
& atomSubtitle? | |
& atomTitle | |
& atomUpdated | |
& extensionElement*), | |
atomEntry* | |
} | |
# atom:entry | |
atomEntry = | |
[ | |
s:rule [ | |
context = "atom:entry" | |
"\x{a}" ~ | |
" " | |
s:assert [ | |
test = | |
"atom:link[@rel='alternate'] or atom:link[not(@rel)] or atom:content" | |
"An atom:entry must have at least one atom:link element with a rel attribute of 'alternate' or an atom:content." | |
] | |
"\x{a}" ~ | |
" " | |
] | |
s:rule [ | |
context = "atom:entry" | |
"\x{a}" ~ | |
" " | |
s:assert [ | |
test = | |
"atom:author or ../atom:author or atom:source/atom:author" | |
"An atom:entry must have an atom:author if its feed does not." | |
] | |
"\x{a}" ~ | |
" " | |
] | |
] | |
element atom:entry { | |
atomCommonAttributes, | |
(atomAuthor* | |
& atomCategory* | |
& atomContent? | |
& atomContributor* | |
& atomId | |
& atomLink* | |
& atomPublished? | |
& atomRights? | |
& atomSource? | |
& atomSummary? | |
& atomTitle | |
& atomUpdated | |
& extensionElement*) | |
} | |
# atom:content | |
atomInlineTextContent = | |
element atom:content { | |
atomCommonAttributes, | |
attribute type { "text" | "html" }?, | |
text* | |
} | |
atomInlineXHTMLContent = | |
element atom:content { | |
atomCommonAttributes, | |
attribute type { "xhtml" }, | |
xhtmlDiv | |
} | |
atomInlineOtherContent = | |
element atom:content { | |
atomCommonAttributes, | |
attribute type { atomMediaType }?, | |
(text | anyElement)* | |
} | |
atomOutOfLineContent = | |
element atom:content { | |
atomCommonAttributes, | |
attribute type { atomMediaType }?, | |
attribute src { atomUri }, | |
empty | |
} | |
atomContent = | |
atomInlineTextContent | |
| atomInlineXHTMLContent | |
| atomInlineOtherContent | |
| atomOutOfLineContent | |
# atom:author | |
atomAuthor = element atom:author { atomPersonConstruct } | |
# atom:category | |
atomCategory = | |
element atom:category { | |
atomCommonAttributes, | |
attribute term { text }, | |
attribute scheme { atomUri }?, | |
attribute label { text }?, | |
undefinedContent | |
} | |
# atom:contributor | |
atomContributor = element atom:contributor { atomPersonConstruct } | |
# atom:generator | |
atomGenerator = | |
element atom:generator { | |
atomCommonAttributes, | |
attribute uri { atomUri }?, | |
attribute version { text }?, | |
text | |
} | |
# atom:icon | |
atomIcon = element atom:icon { atomCommonAttributes, atomUri } | |
# atom:id | |
atomId = element atom:id { atomCommonAttributes, atomUri } | |
# atom:logo | |
atomLogo = element atom:logo { atomCommonAttributes, atomUri } | |
# atom:link | |
atomLink = | |
element atom:link { | |
atomCommonAttributes, | |
attribute href { atomUri }, | |
attribute rel { atomNCName | atomUri }?, | |
attribute type { atomMediaType }?, | |
attribute hreflang { atomLanguageTag }?, | |
attribute title { text }?, | |
attribute length { text }?, | |
undefinedContent | |
} | |
# atom:published | |
atomPublished = element atom:published { atomDateConstruct } | |
# atom:rights | |
atomRights = element atom:rights { atomTextConstruct } | |
# atom:source | |
atomSource = | |
element atom:source { | |
atomCommonAttributes, | |
(atomAuthor* | |
& atomCategory* | |
& atomContributor* | |
& atomGenerator? | |
& atomIcon? | |
& atomId? | |
& atomLink* | |
& atomLogo? | |
& atomRights? | |
& atomSubtitle? | |
& atomTitle? | |
& atomUpdated? | |
& extensionElement*) | |
} | |
# atom:subtitle | |
atomSubtitle = element atom:subtitle { atomTextConstruct } | |
# atom:summary | |
atomSummary = element atom:summary { atomTextConstruct } | |
# atom:title | |
atomTitle = element atom:title { atomTextConstruct } | |
# atom:updated | |
atomUpdated = element atom:updated { atomDateConstruct } | |
# Low-level simple types | |
atomNCName = xsd:string { minLength = "1" pattern = "[^:]*" } | |
# Whatever a media type is, it contains at least one slash | |
atomMediaType = xsd:string { pattern = ".+/.+" } | |
# As defined in RFC 3066 | |
atomLanguageTag = | |
xsd:string { pattern = "[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*" } | |
# Unconstrained; it's not entirely clear how IRI fit into | |
# xsd:anyURI so let's not try to constrain it here | |
atomUri = text | |
# Whatever an email address is, it contains at least one @ | |
atomEmailAddress = xsd:string { pattern = ".+@.+" } | |
# Simple Extension | |
simpleExtensionElement = element * - atom:* { text } | |
# Structured Extension | |
structuredExtensionElement = | |
element * - atom:* { | |
(attribute * { text }+, | |
(text | anyElement)*) | |
| (attribute * { text }*, | |
(text?, anyElement+, (text | anyElement)*)) | |
} | |
# Other Extensibility | |
extensionElement = simpleExtensionElement | structuredExtensionElement | |
undefinedAttribute = | |
attribute * - (xml:base | xml:lang | local:*) { text } | |
undefinedContent = (text | anyForeignElement)* | |
anyElement = | |
element * { | |
(attribute * { text } | |
| text | |
| anyElement)* | |
} | |
anyForeignElement = | |
element * - atom:* { | |
(attribute * { text } | |
| text | |
| anyElement)* | |
} | |
# XHTML | |
anyXHTML = | |
element xhtml:* { | |
(attribute * { text } | |
| text | |
| anyXHTML)* | |
} | |
xhtmlDiv = | |
element xhtml:div { | |
(attribute * { text } | |
| text | |
| anyXHTML)* | |
} | |
# EOF |