/ Robert Sayre <[EMAIL PROTECTED]> was heard to say:
| Norman Walsh wrote:
|
|> The point is that extensions should allow atom:content inside the
|> extension, is that right?
|
| Yes. Any atom element should be allowed in an extension.

Fix appended.

And I happened to notice that our example feed in 1.1 is invalid.
It does not contain an atom:link element with a relation of
"alternat".

# -*- rnc -*-
# RELAX NG Compact Syntax Grammar for the
# Atom Format Specification Version 07+

namespace atom =
   "http://purl.org/atom/ns#draft-ietf-atompub-format-07";
namespace xhtml = "http://www.w3.org/1999/xhtml";
namespace s = "http://www.ascc.net/xml/schematron";

start = atomFeed | atomEntry

# Common attributes

atomCommonAttributes =
   attribute xml:base { atomUri }?,
   attribute xml:lang { atomLanguageTag }?

# 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"
         s:assert [
            test = "atom:[EMAIL PROTECTED]'alternate']"
            "An atom:feed must have at least one link element "
            ~ "with a rel attribute of 'alternate'."
         ]
      ]
      s:rule [
         context = "atom:feed"
         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."
         ]
      ]
   ]
   element atom:feed {
      atomCommonAttributes,
      (atomAuthor?
       & atomCategory*
       & atomContributor*
       & atomCopyright?
       & atomGenerator?
       & atomIcon?
       & atomId?
       & atomImage?
       & atomLink+
       & atomSubtitle?
       & atomTitle
       & atomUpdated
       & extensionElement*),
      atomEntry*
   }

# atom:entry

atomEntry =
   [
      s:rule [
         context = "atom:entry"
         s:assert [
            test = "atom:[EMAIL PROTECTED]'alternate'] or atom:content"
            "An atom:entry must have at least one link element "
            ~ "with a rel attribute of 'alternate' or content."
         ]
      ]
      s:rule [
         context = "atom:entry"
         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."
         ]
      ]

      # N.B. This rule doesn't test for content with a non-binary type.
      s:rule [
         context = "atom:entry"
         s:assert [
            test = "atom:summary or atom:content[not(@src)]"
            "An atom:entry must have an atom:summary "
            ~ "if the atom:content element is empty."
         ]
      ]
   ]
   element atom:entry {
      atomCommonAttributes,
      (atomAuthor?
       & atomCategory*
       & atomContent?
       & atomContributor*
       & atomCopyright?
       & atomId
       & atomLink*
       & atomPublished?
       & 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|anyForeignElement)*
   }

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 }?,
      empty
   }

# atom:contributor

atomContributor = element atom:contributor { atomPersonConstruct }

# atom:copyright

atomCopyright = element atom:copyright { atomTextConstruct }

# atom:generator

atomGenerator = element atom:generator {
   atomCommonAttributes,
   attribute url { atomUri }?,
   attribute version { text }?,
   text
}

# atom:icon

atomIcon = element atom:icon {
   atomCommonAttributes,
   (atomUri)
}

# atom:id

atomId = element atom:id {
   atomCommonAttributes,
   (atomUri)
}

# atom:image

atomImage = element atom:image {
   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 }?,
      empty
   }

# atom:published

atomPublished = element atom:published { atomDateConstruct }

# atom:source

atomSource =
   element atom:source {
      atomCommonAttributes,
      (atomAuthor?
       & atomCategory*
       & atomContributor*
       & atomCopyright?
       & atomGenerator?
       & atomIcon?
       & atomId?
       & atomImage?
       & atomLink+
       & 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 = "[EMAIL PROTECTED]" }

# Extensibility

simpleExtensionElement =
   element * - atom:* {
      text
   }

structuredExtensionElement =
   element * - atom:* {
      (attribute * { text }+,
         (text|anyElement)*)
    | (attribute * { text }*,
       (text?, anyElement+, (text|anyElement)*))
   }

extensionElement =
   simpleExtensionElement | structuredExtensionElement

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

                                        Be seeing you,
                                          norm

-- 
Norman Walsh <[EMAIL PROTECTED]> | Everything should be made as simple as
http://nwalsh.com/            | possible, but no simpler.

Attachment: pgpKvsmTSZu2H.pgp
Description: PGP signature

Reply via email to