blob: 327b49970afee42f29bd8595a881ab531a40697b [file] [log] [blame]
# =========================================================
#
# (c) 2004, RenderX
#
# Author: Alexander Peshkov <peshkov@renderx.com>
#
# Permission is granted to use this document, copy and
# modify free of charge, provided that every derived work
# bear a reference to the present document.
#
# This document contains a computer program written in
# XSL Transformations Language. It is published with no
# warranty of any kind about its usability, as a mere
# example of XSL technology. RenderX shall not be
# considered liable for any damage or loss of data caused
# by use of this program.
#
# =========================================================
namespace local = ""
default namespace fo = "http://www.w3.org/1999/XSL/Format"
namespace rx = "http://www.renderx.com/XSL/Extensions"
include "properties.rnc"
# ****************************************************************************************
# Common content models used by content-bearing elements
# ****************************************************************************************
very-basic-inlines =
character
| external-graphic
| instream-foreign-object
| inline-container
| leader
| page-number
| page-number-citation
| multi-toggle #MEMO: To be strict, we have to control that this element is a descendant of an fo:multi-case.
| page-index
| begin-index-range
| end-index-range
#NOTE: An absolute-container can be treated both as block and as outline.
basic-blocks =
block | block-container | table-and-caption | table | list-block
#NOTE: Unlike other out-of-lines fo:footnote can be used only in the context where inlines are permitted
out-of-lines-block = before-float | side-float | absolute-container
out-of-lines = footnote | out-of-lines-block
# As a compromise for intricated inline content model prescribed by XSL FO spec
# we define two types of inline content:
# first as restrictive as required by spec for descendants of an fo:leader or of an fo:inline
# child of an fo:footnote (and for some other cases where we believe it is reasonable),
# it permits inline level elements only, except for descendants of fo:inline-container;
# second as loose as prescribed by spec for the general cases
basic-inlines-inline = very-basic-inlines | basic-link-inline | inline-inline | bidi-override-inline
basic-inlines = very-basic-inlines | basic-link | inline | bidi-override
# We have three content models for wrappers:
# first one allows inline content only (based on basic-inlines-inline described above);
# second one requires block-level elements to be at the top of it;
# third one is for mixed content (general case);
wrappers-inline =
multi-switch-inline | multi-properties-inline | wrapper-inline | retrieve-marker
wrappers-block =
multi-switch-block | multi-properties-block | wrapper-block | retrieve-marker
wrappers =
multi-switch | multi-properties | wrapper | retrieve-marker
# We have two extended content models for inlines:
# first one is stricter, with inline elements only (exception for fo:inline-container descendants)
# and with no outlines (actually they are bared in main.rnc anyway);
# second one is loose, with all possible inlines and outlines.
# In general those content models corresponds very well with two possible contexts:
# block context and inline context
inlines-inline = text | basic-inlines-inline | wrappers-inline
inlines = text | basic-inlines | out-of-lines | wrappers
# Content model for blocks including block-level outlines
blocks = basic-blocks | wrappers-block | out-of-lines-block
# Mixed content model - broadest one
mix = inlines | basic-blocks
# ****************************************************************************************
# Element structure for content-bearing elements
# ****************************************************************************************
# ===============================================================
# Block is the base element for all content areas.
# ===============================================================
block =
element fo:block {
block.attlist, block.content
}
block.content = marker*, ( initial-property-set | mix )*
# ===============================================================
# Block container
# ===============================================================
#MEMO: We are forced to create separate element 'absolute-container' in order
# to satisfy XSL FO spec requirements. Note that this is the *only* place where
# properties really interfer with element-level structure (well, actually fo:float is the second place).
# A separate fo:absolute-container is clearly necessary.
# Absolutely possitioned block-container cannot contain markers and and outlines.
# It's behaviour is quite similar to the outline elements such as float.
# 'Folint' do not control absolutely positioned container restriction
# (due to expressions that can result in absolute position)
# 'Folint' also permits empty block-containers, that is against the spec.
# Spec defines fo:block-container content as (%block;)+
absolute-container = notAllowed
absolute-container-real =
element fo:block-container { absolute-container.attlist, absolute-container.content }
absolute-container.content = blocks+
block-container =
element fo:block-container { block-container.attlist, block-container.content }
block-container.content = marker*, blocks+
# ****************************************************************************************
# Inline elements
# ****************************************************************************************
# ===============================================================
# Unicode bidi-override
# ===============================================================
#MEMO: According to spec this element CAN have block level children except for the cases listed below:
# XSL> An fo:bidi-override that is a descendant of an fo:leader or of an fo:inline child
# XSL> of an fo:footnote may not have block-level children, unless it has a nearer ancestor
# XSL> that is an fo:inline-container.
# NOTE: This is contradictory to the description of fo:leader element (6.6.9. fo:leader) that
# prohibits (some) block-level elements/outlines to be fo:leader descendants
# no matter if they wrapped in any fo:inline-containers and fo:bidi-override.
# We have two models:
# first (restrictive) used by descendants of an fo:title, fo:leader or of an fo:inline child of an fo:footnote;
# second (loose) as prescribed by spec for the general cases
# 'Folint' believes that no block level elements should be allowed in this element in either way.
bidi-override-inline =
element fo:bidi-override { bidi-override.attlist, bidi-override-inline.content }
bidi-override-inline.content = marker*, inlines-inline*
bidi-override =
element fo:bidi-override { bidi-override.attlist, bidi-override.content }
bidi-override.content = marker*, mix*
# ===============================================================
# Single character
# ===============================================================
character = element fo:character { character.attlist, empty }
# ===============================================================
# Initial property set specifies properties for one or more lines
# ===============================================================
initial-property-set =
element fo:initial-property-set {
initial-property-set.attlist, empty
}
# ===============================================================
# External graphic
# ===============================================================
external-graphic =
element fo:external-graphic { external-graphic.attlist, empty }
# ===============================================================
# In-stream graphic
# ===============================================================
instream-foreign-object =
element fo:instream-foreign-object {
instream-foreign-object.attlist, any
}
# ===============================================================
# Inline
# ===============================================================
#MEMO: This element used by content model that consists of inlines only
# with exception for descendants of inline-container
inline-inline = element fo:inline { inline.attlist, inline-inline.content }
inline-inline.content = marker*, inlines-inline*
inline = element fo:inline { inline.attlist, inline.content }
inline.content = marker*, mix*
# XSL> An fo:inline that is a child of an fo:footnote may not have block-level children.
# XSL> An fo:inline that is a descendant of an fo:leader or of the fo:inline child of
# XSL> an fo:footnote may not have block-level children, unless it has a nearer
# XSL> ancestor that is an fo:inline-container.
#NOTE: This definition is contradictory to the one of the fo:leader since latter prohibits
# fo:inline-container as a descendant. But it's the definition of fo:leader that should be fixed
# since content model described above is the only sane content model in the inline context.
# It should be the same for fo:bidi-override. However definition must be adjasted
# in order to mention fo:title since this element is a typical inline.
#
# 'Folint' believes that block elements are allowed here and thoroughly tests for
# all those tricky exceptions. This behavior seems to be quite inconsisten with the
# one regarding fo:bidi-override treatment.
# ===============================================================
# Inline container
# ===============================================================
inline-container =
element fo:inline-container { inline-container.attlist, inline-container.content }
inline-container.content = marker*, blocks*
# ===============================================================
# Leader
# ===============================================================
leader = element fo:leader { leader.attlist, leader.content }
leader.content = inlines-inline*
#MEMO: Following two lines used together with tricky redefinition in main.rnc
# in order to prevent fo:leader nesting.
#leader.content = notAllowed
#leader.content-real = inlines-inline*
#MEMO: We use inline content model here which is consistent with
# such elements as fo:inline child of fo:footnote. It allows blocks/outlines, but only as a
# descendant of inline-container. XSL FO spec is quite uneven at this point (and should be fixed).
# According to spec, this element can contain inline level elements and text, but
# XSL> The content must not contain an fo:leader, fo:inline-container, fo:block-container,
# XSL> fo:float, fo:footnote, or fo:marker either as a direct child or as a descendant.
# NOTE: XSL FO spec DO NOT prohibit blocks or tables as descendants of fo:leader!
# NOTE: fo:leader constraints are contradictory to those of fo:inline since section "6.6.7. fo:inline"
# states implicitly that there could be an fo:inline-container that is a descendent of fo:leader.
#
# 'Folint' respects these constraints partially: it prohibits fo:block-container as a descendant,
# but permits fo:marker, fo:leader, fo:inline-container, fo:float, fo:footnote.
# It also prohibits use of fo:block as descendant.
# ===============================================================
# Page Number
# ===============================================================
page-number = element fo:page-number { page-number.attlist, empty }
# ===============================================================
# Page number citation
# ===============================================================
page-number-citation =
element fo:page-number-citation {
page-number-citation.attlist, empty
}
# ===============================================================
# Atomic elements for index ranges markup
# ===============================================================
begin-index-range =
element rx:begin-index-range { begin-index-range.attlist, empty }
end-index-range =
element rx:end-index-range { end-index-range.attlist, empty }
# ===============================================================
# Page number list - index entry
# ===============================================================
page-index = element rx:page-index { page-index.attlist, page-index.content }
#MEMO: Currently page-index must contain at least one rx:index-item element,
# empty content is allowed for backward compatibility.
page-index.content = index-item*
index-item = element rx:index-item { index-item.attlist, empty }
# ****************************************************************************************
# Formatting objects for tables.
# ****************************************************************************************
# ===============================================================
# Table & Caption is a wrapper to all the stuff pertinent to a
# given table. It generates a block consisting of two subblocks:
# one for the caption, another one for the table itself. The
# placement of these two blocks is controlled by the
# 'caption-side' property: if caption-side="before"|"after" (or
# their absolute orientation equivalents), the two blocks are
# drawn one after another; if it is "start"|"end", then the
# caption is displayed on the correspondent side of the table.
# In this case, the relative alignment of the two blocks is given
# by the 'relative-align'/'display-align' property.
#
# ===============================================================
table-and-caption =
element fo:table-and-caption {
table-and-caption.attlist,
table-and-caption.content
}
table-and-caption.content = marker*, table-caption?, table
# ===============================================================
# Table caption is an area container.
# ===============================================================
table-caption =
element fo:table-caption { table-caption.attlist, table-caption.content }
table-caption.content = marker*, blocks+
# ===============================================================
# fo:table is the basic element for all tables. All the contents
# placed inside it is distributed over a single rectangular grid
# of rows and columns.
# ===============================================================
table =
element fo:table {
table.attlist,
table.content
}
table.content =
marker*,
table-column*,
table-header?,
table-footer?,
table-body+
# ===============================================================
# Table column specifies common properties to ascribe to all
# cells in a column *or a group of columns*. Note that, if both
# 'number-columns-repeated' and 'number-columns-spanned' exceed
# 1, the column counter is increased by 'number-columns-spanned'.
# it means that you only set properties for columns:
# 'column-number'
# 'column-number' + 'number-columns-spanned'
# 'column-number' + 2 * 'number-columns-spanned'
# and so on, leaving default properties for intermediate columns.
# ===============================================================
table-column = element fo:table-column { table-column.attlist, empty }
# ===============================================================
# Table header, table footer, and table body are wrappers for
# groups of rows. They contain either one or more fo:table-rows,
# or one or more fo:table-cells; in the latter case, row breaks
# are specified in the cells by 'starts-row'/'ends-row'.
# All these elements are identical both in the content structure
# and in the attributes.
# ===============================================================
row-group = marker*, (table-row+ | table-cell+)
table-header =
element fo:table-header { table-header.attlist, table-header.content }
table-header.content = row-group
table-footer =
element fo:table-footer { table-footer.attlist, table-footer.content }
table-footer.content = row-group
table-body = element fo:table-body { table-body.attlist, table-body.content }
table-body.content = row-group
# ===============================================================
# Table row.
# ===============================================================
table-row = element fo:table-row { table-row.attlist, table-row.content }
table-row.content = table-cell+
#MEMO: We are more strict here, so this note is about 'Folint':
# 'Folint' permits empty fo:table-row, that is against the spec.
# XSL FO spec defines fo:table-row content as (table-cell+)
# ===============================================================
# Table cell.
# ===============================================================
table-cell = element fo:table-cell { table-cell.attlist, table-cell.content }
table-cell.content = marker*, blocks+
#MEMO: We are more strict here, so this note is about 'Folint':
# 'Folint' permits empty table-cells that is against the spec. Spec defines fo:table-cell
# content as (%block;)+
# Note that 'Folint' is quite consistent regarding this matter - it simillary allows empty
# block-containers and table-rows
# ****************************************************************************************
# Formatting objects for lists.
# ****************************************************************************************
# ===============================================================
# List block is a block, with some extra features to control the
# disposition of list items.
# ===============================================================
list-block = element fo:list-block { list-block.attlist, list-block.content }
list-block.content = marker*, list-item+
# ===============================================================
# List item is a coupling of item label and item body.
# ===============================================================
list-item =
element fo:list-item {
list-item.attlist,
list-item.content
}
list-item.content = marker*, list-item-label, list-item-body
# ===============================================================
# List item label and list item body
# ===============================================================
list-item-label =
element fo:list-item-label { list-item-label.attlist, list-item-label.content }
list-item-label.content = marker*, blocks+
list-item-body =
element fo:list-item-body { list-item-body.attlist, list-item-body.content }
list-item-body.content = marker*, blocks+
#MEMO: We are more strict here, so this note is about 'Folint':
# 'Folint' permits empty fo:list-item-label/body, that is clearly the spec.
# Spec defines fo:list-item-label/body content as (%block;)+
#****************************************************************************************
# Out-of-lines.
#****************************************************************************************
# ===============================================================
# Floats and footnotes resemble containers. Accordingly, we treat
# them as block sequences.
# ===============================================================
#MEMO: We do not allows absolutely positioned container as an outline descendant.
# 'Folint' is loose here - it do not check this condition.
#MEMO: We are forced to create two types of floats: side-floats and before-floats
# because they have different restrictions (side-floats can appear in static content,
# before-floats can't bear 'clear' property)
# NOTE: 'Folint' does not allows any floats inside absolutely positioned containers too.
side-float = notAllowed
side-float-real = element fo:float { side-float.attlist, float.content }
before-float = notAllowed
before-float-real = element fo:float { before-float.attlist, float.content }
float.content = blocks+
# XSL> It is an error if the fo:footnote occurs as a descendant of a flow that is not assigned
# XSL> to a region-body, or of an fo:block-container that generates absolutely positioned areas.
footnote = notAllowed
footnote-real =
element fo:footnote { footnote.attlist, footnote.content }
# XSL> An fo:inline that is a child of an fo:footnote may not have block-level children.
# XSL> An fo:inline that is a descendant of an fo:leader or of the fo:inline child of
# XSL> an fo:footnote may not have block-level children, unless it has a nearer
# XSL> ancestor that is an fo:inline-container.
# We do check here that first inline have no block-level children/descendants unlless
# they are wrapped into an inline-container.
# 'Folint' does the same.
footnote.content = inline-inline, footnote-body
footnote-body =
element fo:footnote-body { footnote-body.attlist, footnote-body.content }
footnote-body.content = blocks+
# ===============================================================
# Simple link. From the formatting point of view, it's nothing
# but a regular inline sequence.
# ===============================================================
# This elment is for separate 'inline' content model
basic-link-inline = element fo:basic-link { basic-link.attlist, basic-link-inline.content }
basic-link-inline.content = marker*, inlines-inline*
basic-link = element fo:basic-link { basic-link.attlist, basic-link.content }
basic-link.content = marker*, mix*
# ****************************************************************************************
# Wrappers and Markers.
# ****************************************************************************************
# ===============================================================
# Wrapper. This may be useful but it seriously complicates validation of
# content models for blocks and inlines.
# ===============================================================
#There are 3 different kind of wrappers for different contexts
wrapper-inline = element fo:wrapper { wrapper.attlist, wrapper-inline.content }
wrapper-inline.content = marker*, inlines-inline*
wrapper-block = element fo:wrapper { wrapper.attlist, wrapper-block.content }
wrapper-block.content = marker*, blocks*
wrapper = element fo:wrapper { wrapper.attlist, wrapper.content }
wrapper.content = marker*, mix*
# ===============================================================
# Marker.
# ===============================================================
marker = notAllowed
marker-real = element fo:marker { marker.attlist, marker.content }
marker.content = mix*
# ===============================================================
# Marker retrieval.
# We are more strict here making retrieve-class-name attribute a mandatory,
# but marker with no retrieve-class-name is meaningless.
# ===============================================================
retrieve-marker = notAllowed
retrieve-marker-real = element fo:retrieve-marker { retrieve-marker.attlist, empty }
# ****************************************************************************************
# Multistate stuff.
# All those elements are practically unused and XSL content model invloved is
# intricated. Therefor validation is not absolutely strict here.
# ****************************************************************************************
# ===============================================================
# Switch. This is a pure logical operator; no formatting may be
# conveyed through it.
# ===============================================================
#Thera are 3 different kind of multi-switch (because there are 3 kinds of multi-case)
multi-switch-inline =
element fo:multi-switch { multi-switch.attlist, multi-switch-inline.content }
multi-switch-inline.content = multi-case-inline+
multi-switch-block =
element fo:multi-switch { multi-switch.attlist, multi-switch-block.content }
multi-switch-block.content = multi-case-block+
multi-switch =
element fo:multi-switch { multi-switch.attlist, multi-switch.content }
multi-switch.content = multi-case+
# ===============================================================
# Single case. Block-level formatting may be conveyed.
# ===============================================================
#Thera are 3 different kind of multi-case (similar to fo:wrapper)
multi-case-inline = element fo:multi-case { multi-case.attlist, multi-case-inline.content }
multi-case-inline.content = inlines-inline*
multi-case-block = element fo:multi-case { multi-case.attlist, multi-case-block.content }
multi-case-block.content = blocks*
multi-case = element fo:multi-case { multi-case.attlist, multi-case.content }
multi-case.content = mix*
# ===============================================================
# Toggle. This is a typical inline.
# ===============================================================
#MEMO: This element is only permitted as a descendant of an fo:multi-case.
multi-toggle =
element fo:multi-toggle { multi-toggle.attlist, multi-toggle.content }
multi-toggle.content = mix*
# ===============================================================
# Multi-properties.
# ===============================================================
#Thera are 3 different kind of multi-properties (similar to fo:wrapper)
multi-properties-inline =
element fo:multi-properties {
multi-properties.attlist, multi-properties-inline.content
}
multi-properties-inline.content = multi-property-set+, wrapper-inline
multi-properties-block =
element fo:multi-properties {
multi-properties.attlist, multi-properties-block.content
}
multi-properties-block.content = multi-property-set+, wrapper-block
multi-properties =
element fo:multi-properties {
multi-properties.attlist, multi-properties.content
}
multi-properties.content = multi-property-set+, wrapper
# ===============================================================
# Multi property set.
# ===============================================================
multi-property-set =
element fo:multi-property-set { multi-property-set.attlist, empty }
# ===============================================================
# "Match anything" definition, used by fo:instream-foreign-object
# ===============================================================
#MEMO: Should we exclude elements which belongs to fo: namespace?
any =
(element * {
attribute * { text }*,
any
}
| text)*