summaryrefslogtreecommitdiff
path: root/info/examples/lwc/ch7
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /info/examples/lwc/ch7
Initial commit
Diffstat (limited to 'info/examples/lwc/ch7')
-rw-r--r--info/examples/lwc/ch7/README.ch7124
-rw-r--r--info/examples/lwc/ch7/SGMLS.pm893
-rw-r--r--info/examples/lwc/ch7/SGMLS/Output.pm225
-rw-r--r--info/examples/lwc/ch7/SGMLS/Refs.pm216
-rw-r--r--info/examples/lwc/ch7/SGMLS/SGMLS.pm893
-rw-r--r--info/examples/lwc/ch7/any.xml18
-rw-r--r--info/examples/lwc/ch7/any.xsl25
-rw-r--r--info/examples/lwc/ch7/catalog5
-rw-r--r--info/examples/lwc/ch7/catalog.dsssl3
-rw-r--r--info/examples/lwc/ch7/catalog.xml2
-rw-r--r--info/examples/lwc/ch7/debug.txt789
-rw-r--r--info/examples/lwc/ch7/dsssl.cat3
-rw-r--r--info/examples/lwc/ch7/dsssl.dtd134
-rw-r--r--info/examples/lwc/ch7/empty.dsl8
-rw-r--r--info/examples/lwc/ch7/empty.xsl2
-rw-r--r--info/examples/lwc/ch7/emptyexample.xml15
-rw-r--r--info/examples/lwc/ch7/fot.dtd507
-rw-r--r--info/examples/lwc/ch7/inv1html.pl61
-rw-r--r--info/examples/lwc/ch7/inv2css.html.save44
-rw-r--r--info/examples/lwc/ch7/inv2html.pl61
-rw-r--r--info/examples/lwc/ch7/inv2lat.pl76
-rw-r--r--info/examples/lwc/ch7/inv3.xml21
-rw-r--r--info/examples/lwc/ch7/invcss.html.save44
-rw-r--r--info/examples/lwc/ch7/invfo1.fop21
-rw-r--r--info/examples/lwc/ch7/invfo1.out50
-rw-r--r--info/examples/lwc/ch7/invfo1.pdf319
-rw-r--r--info/examples/lwc/ch7/invfo1.xsl80
-rw-r--r--info/examples/lwc/ch7/invhtml.dsl90
-rw-r--r--info/examples/lwc/ch7/invhtml2.xsl43
-rw-r--r--info/examples/lwc/ch7/invit.css31
-rw-r--r--info/examples/lwc/ch7/invitation.dsl66
-rw-r--r--info/examples/lwc/ch7/invitation.dtd14
-rw-r--r--info/examples/lwc/ch7/invitation.fot38
-rw-r--r--info/examples/lwc/ch7/invitation.sty30
-rw-r--r--info/examples/lwc/ch7/invitation.tex.save27
-rw-r--r--info/examples/lwc/ch7/invitation.xml29
-rw-r--r--info/examples/lwc/ch7/invitation2.dtd15
-rw-r--r--info/examples/lwc/ch7/invitation2.xml20
-rw-r--r--info/examples/lwc/ch7/invitationfr.sty50
-rw-r--r--info/examples/lwc/ch7/invlat1.xsl63
-rw-r--r--info/examples/lwc/ch7/invtab1.dsl82
-rw-r--r--info/examples/lwc/ch7/invtab2.dsl75
-rw-r--r--info/examples/lwc/ch7/makesum.xml5
-rw-r--r--info/examples/lwc/ch7/makesum.xsl16
-rw-r--r--info/examples/lwc/ch7/sectionexa.xml22
-rw-r--r--info/examples/lwc/ch7/sectionexa.xsl72
-rw-r--r--info/examples/lwc/ch7/sgmlspl.pl317
-rw-r--r--info/examples/lwc/ch7/skel.pl178
-rw-r--r--info/examples/lwc/ch7/style-sheet.dtd41
-rw-r--r--info/examples/lwc/ch7/templatest.xml3
-rw-r--r--info/examples/lwc/ch7/templatest.xsl41
-rw-r--r--info/examples/lwc/ch7/templatestnok.xsl41
-rw-r--r--info/examples/lwc/ch7/templatestok.xsl31
-rw-r--r--info/examples/lwc/ch7/test-SGMLS.pl13
-rw-r--r--info/examples/lwc/ch7/writefile.xsl8
-rw-r--r--info/examples/lwc/ch7/writefiles.xml9
-rw-r--r--info/examples/lwc/ch7/wrong.xml15
-rw-r--r--info/examples/lwc/ch7/xml.dcl179
-rw-r--r--info/examples/lwc/ch7/xsl.xml3838
-rw-r--r--info/examples/lwc/ch7/xslexa1.xsl30
60 files changed, 10171 insertions, 0 deletions
diff --git a/info/examples/lwc/ch7/README.ch7 b/info/examples/lwc/ch7/README.ch7
new file mode 100644
index 0000000000..29a6953802
--- /dev/null
+++ b/info/examples/lwc/ch7/README.ch7
@@ -0,0 +1,124 @@
+Examples in Chapter 7 of the LaTeX Graphics Companion
+
+Section 7.3
+===========
+
+To run the examples in this section you have to install nsgmls
+(as for chapter 6) and Megginson's SGMLSpm. You also have to
+set the environment variable SGML_CATALOG_FILES as follows:
+
+Bourne shell
+
+SGML_CATALOG_FILES=catalog.xml
+export SGML_CATALOG_FILES
+
+C shell
+
+setenv SGML_CATALOG_FILES catalog.xml
+
+Then you can type:
+
+nsgmls invitation.xml | perl sgmlspl.pl inv2lat.pl > invitation.tex
+
+Section 7.4
+===========
+
+With similar settings for the environment variable SGML_CATALOG_FILES
+we can generate HTML files using invitation.xml and invitation2.xml.
+
+We type the command (Section 7.4.4)
+
+nsgmls invitation.xml | perl sgmlspl.pl inv1html.pl > invcss.html
+
+and (Section 7.4.5)
+
+nsgmls invitation2.xml | perl sgmlspl.pl inv2html.pl > inv2css.html
+
+Together with the file invit.css, shown in Section 7.4.4, you will
+obtain with a browser, which correctly understands how to include CSS
+files, a view as the one shown in Figure 7.2 (some browsers might need
+you to include the content of invit.css inside a <STYLE> tag pair
+inside the HTML file). Browsers can treat empty lines differently, so
+you might observe more or less white space between paragraphs
+depending on the browser used.
+
+Section 7.5
+===========
+
+To run jade (and DSSSL style-sheets) we need a different catalog
+file, so we redefine SGML_CATALOG_FILES=catalog.dsssl (or the
+equivalent in C-like shells).
+
+Then we run as shown on page 320 (copying element content through)
+
+jade -t xml -d empty.dsl invitation.xml
+
+Then you can run
+
+jade -d invitation.dsl invitation.xml
+
+
+Files in this directory:
+========================
+
+Section 7.3
++++++++++++
+
+invitation.xml XML source introduced in Section 6.4.2.2
+invitation.dtd DTD source introduced in Section 6.4.3
+invitation.tex.save result of Perl run of Section 7.3.2
+invitation.sty package file for invitation examples (Section 7.3.2)
+catalog.xml catalog file for nsgmls to define XML declaration
+
+inv1html.pl Perl file to run example of Section 7.4.4
+inv2lat.pl Perl file to run example of Section 7.3.2
+sgmlspl.pl Perl files distributed with the SGMLSpl package
+skel.pl " "
+SGMLS.pm " "
+SGMLS/Output.pm " "
+SGMLS/Refs.pm " "
+
+Section 7.4
++++++++++++
+
+invitation2.xml XML source introduced in Section 7.4.5
+invitation2.dtd DTD source introduced in Section 7.4.5
+invit.css CSS style sheet introduced in Section 7.4.4
+invcss.html.save result HTML output for Section 7.4.4
+inv2css.html.save result HTML output for Section 7.4.6
+
+Section 7.5
++++++++++++
+
+catalog.dsssl catalog file for jade to define DSSSL style-sheet
+empty.dsl trivial DSSSL style-sheet copying element content
+ through to the output
+invitation.dsl used in Section 7.5.3.1
+invtab1.dsl used in Section 7.5.3.2
+invtab2.dsl used in Section 7.5.3.3
+invhtml.dsl used in Section 7.5.5
+
+Section 7.6
++++++++++++
+
+xslexa1.xsl formatting object example (Section 7.6.1)
+
+empty.xsl trivial XSL style-sheet (Section 7.6.3)
+
+sectionexa.xml example XML source
+sextionexa.xsl ... and XSL style-sheet (Section 7.6.5.7)
+
+writefiles.xml example XML source
+writefile.xsl ... and XSL style-sheet (Section 7.6.8.2)
+
+makesum.xml example XML source
+makesum.xsl ... and XSL style-sheet (Section 7.6.8.2)
+
+invlat1.xsl XSL style-sheet for Section 7.6.9
+invhtml2.xsl " "
+invfo1.xsl XSL style-sheet for Section 7.6.10
+ (was modified to retain August 1998 syntax for
+ fo's since fop is not yet updated)
+
+invfo1.fop intermediate output for fop (contains fo's)
+invfo1.pdf generated PDF output \ No newline at end of file
diff --git a/info/examples/lwc/ch7/SGMLS.pm b/info/examples/lwc/ch7/SGMLS.pm
new file mode 100644
index 0000000000..b29395eed3
--- /dev/null
+++ b/info/examples/lwc/ch7/SGMLS.pm
@@ -0,0 +1,893 @@
+package SGMLS;
+use Carp;
+
+$version = '$Revision: 1.14 $';
+
+=head1 NAME
+
+SGMLS - class for postprocessing the output from the B<sgmls> and
+B<nsgmls> parsers.
+
+=head1 SYNOPSIS
+
+ use SGMLS;
+
+ my $parse = new SGMLS(STDIN);
+
+ my $event = $parse->next_event;
+ while ($event) {
+
+ SWITCH: {
+
+ ($event->type eq 'start_element') && do {
+ my $element = $event->data; # An object of class SGMLS_Element
+ [[your code for the beginning of an element]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'end_element') && do {
+ my $element = $event->data; # An object of class SGMLS_Element
+ [[your code for the end of an element]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'cdata') && do {
+ my $cdata = $event->data; # A string
+ [[your code for character data]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'sdata') && do {
+ my $sdata = $event->data; # A string
+ [[your code for system data]]
+ last SWITCH;
+ };
+
+ ($event->type eq 're') && do {
+ [[your code for a record end]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'pi') && do {
+ my $pi = $event->data; # A string
+ [[your code for a processing instruction]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'entity') && do {
+ my $entity = $event->data; # An object of class SGMLS_Entity
+ [[your code for an external entity]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'start_subdoc') && do {
+ my $entity = $event->data; # An object of class SGMLS_Entity
+ [[your code for the beginning of a subdoc entity]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'end_subdoc') && do {
+ my $entity = $event->data; # An object of class SGMLS_Entity
+ [[your code for the end of a subdoc entity]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'conforming') && do {
+ [[your code for a conforming document]]
+ last SWITCH;
+ };
+
+ die "Internal error: unknown event type " . $event->type . "\n";
+ }
+
+ $event = $parse->next_event;
+ }
+
+=head1 DESCRIPTION
+
+The B<SGMLS> package consists of several related classes: see
+L<"SGMLS">, L<"SGMLS_Event">, L<"SGMLS_Element">,
+L<"SGMLS_Attribute">, L<"SGMLS_Notation">, and L<"SGMLS_Entity">. All
+of these classes are available when you specify
+
+ use SGMLS;
+
+Generally, the only object which you will create explicitly will
+belong to the C<SGMLS> class; all of the others will then be created
+automatically for you over the course of the parse. Much fuller
+documentation is available in the C<.sgml> files in the C<DOC/>
+directory of the C<SGMLS.pm> distribution.
+
+=head2 The C<SGMLS> class
+
+This class holds a single parse. When you create an instance of it,
+you specify a file handle as an argument (if you are reading the
+output of B<sgmls> or B<nsgmls> from a pipe, the file handle will
+ordinarily be C<STDIN>):
+
+ my $parse = new SGMLS(STDIN);
+
+The most important method for this class is C<next_event>, which reads
+and returns the next major event from the input stream. It is
+important to note that the C<SGMLS> class deals with most B<ESIS>
+events itself: attributes and entity definitions, for example, are
+collected and stored automatically and invisibly to the user. The
+following list contains all of the methods for the C<SGMLS> class:
+
+=item C<next_event()>: Return an C<SGMLS_Event> object containing the
+next major event from the SGML parse.
+
+=item C<element()>: Return an C<SGMLS_Element> object containing the
+current element in the document.
+
+=item C<file()>: Return a string containing the name of the current
+SGML source file (this will work only if the C<-l> option was given to
+B<sgmls> or B<nsgmls>).
+
+=item C<line()>: Return a string containing the current line number
+from the source file (this will work only if the C<-l> option was
+given to B<sgmls> or B<nsgmls>).
+
+=item C<appinfo()>: Return a string containing the C<APPINFO>
+parameter (if any) from the SGML declaration.
+
+=item C<notation(NNAME)>: Return an C<SGMLS_Notation> object
+representing the notation named C<NNAME>. With newer versions of
+B<nsgmls>, all notations are available; otherwise, only the notations
+which are actually used will be available.
+
+=item C<entity(ENAME)>: Return an C<SGMLS_Entity> object representing
+the entity named C<ENAME>. With newer versions of B<nsgmls>, all
+entities are available; otherwise, only external data entities and
+internal entities used as attribute values will be available.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Event> class
+
+This class holds a single major event, as generated by the
+C<next_event> method in the C<SGMLS> class. It uses the following
+methods:
+
+=item C<type()>: Return a string describing the type of event:
+"start_element", "end_element", "cdata", "sdata", "re", "pi",
+"entity", "start_subdoc", "end_subdoc", and "conforming". See
+L<"SYNOPSIS">, above, for the values associated with each of these.
+
+=item C<data()>: Return the data associated with the current event (if
+any). For "start_element" and "end_element", returns an
+C<SGMLS_ELement> object; for "entity", "start_subdoc", and
+"end_subdoc", returns an C<SGMLS_Entity> object; for "cdata", "sdata",
+and "pi", returns a string; and for "re" and "conforming", returns the
+empty string. See L<"SYNOPSIS">, above, for an example of this
+method's use.
+
+=item C<key()>: Return a string key to the event, such as an element
+or entity name (otherwise, the same as C<data()>).
+
+=item C<file()>: Return the current file name, as in the C<SGMLS>
+class.
+
+=item C<line()>: Return the current line number, as in the C<SGMLS>
+class.
+
+=item C<element()>: Return the current element, as in the C<SGMLS>
+class.
+
+=item C<parse()>: Return the C<SGMLS> object which generated the
+event.
+
+=item C<entity(ENAME)>: Look up an entity, as in the C<SGMLS> class.
+
+=item C<notation(ENAME)>: Look up a notation, as in the C<SGMLS>
+class.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Element> class
+
+This class is used for elements, and contains all associated
+information (such as the element's attributes). It recognises the
+following methods:
+
+=item C<name()>: Return a string containing the name, or Generic
+Identifier, of the element, in upper case.
+
+=item C<parent()>: Return the C<SGMLS_Element> object for the
+element's parent (if any).
+
+=item C<parse()>: Return the C<SGMLS> object for the current parse.
+
+=item C<attributes()>: Return a reference to an associative array of
+attribute names and C<SGMLS_Attribute> structures. Attribute names
+will be all in upper case.
+
+=item C<attribute_names()>: Return an array of strings containing the
+names of all attributes defined for the current element, in upper
+case.
+
+=item C<attribute(ANAME)>: Return the C<SGMLS_Attribute> structure for
+the attribute C<ANAME>.
+
+=item C<set_attribute(ATTRIB)>: Add the C<SGMLS_Attribute> object
+C<ATTRIB> to the current element, replacing any other attribute
+structure with the same name.
+
+=item C<in(GI)>: Return C<true> (ie. 1) if the string C<GI> is the
+name of the current element's parent, or C<false> (ie. 0) if it is
+not.
+
+=item C<within(GI)>: Return C<true> (ie. 1) if the string C<GI> is the
+name of any of the ancestors of the current element, or C<false>
+(ie. 0) if it is not.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Attribute> class
+
+Each instance of an attribute for each C<SGMLS_Element> is an object
+belonging to this class, which recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the current
+attribute, all in upper case.
+
+=item C<type()>: Return a string containing the type of the current
+attribute, all in upper case. Available types are "IMPLIED", "CDATA",
+"NOTATION", "ENTITY", and "TOKEN".
+
+=item C<value()>: Return the value of the current attribute, if any.
+This will be an empty string if the type is "IMPLIED", a string of
+some sort if the type is "CDATA" or "TOKEN" (if it is "TOKEN", you may
+want to split the string into a series of separate tokens), an
+C<SGMLS_Notation> object if the type is "NOTATION", or an
+C<SGMLS_Entity> object if the type is "ENTITY". Note that if the
+value is "CDATA", it will I<not> have escape sequences for 8-bit
+characters, record ends, or SDATA processed -- that will be your
+responsibility.
+
+=item C<is_implied()>: Return C<true> (ie. 1) if the value of the
+attribute is implied, or C<false> (ie. 0) if it is specified in the
+document.
+
+=item C<set_type(TYPE)>: Change the type of the attribute to the
+string C<TYPE> (which should be all in upper case). Available types
+are "IMPLIED", "CDATA", "NOTATION", "ENTITY", and "TOKEN".
+
+=item C<set_value(VALUE)>: Change the value of the attribute to
+C<VALUE>, which may be a string, an C<SGMLS_Entity> object, or an
+C<SGMLS_Notation> subject, depending on the attribute's type.
+
+=item C<ext()>: Return a reference to an associative array available
+for user-defined extensions.
+
+
+=head2 The C<SGMLS_Notation> class
+
+All declared notations appear as objects belonging to this class,
+which recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the notation.
+
+=item C<sysid()>: Return a string containing the system identifier of
+the notation, if any.
+
+=item C<pubid()>: Return a string containing the public identifier of
+the notation, if any.
+
+=item C<ext()>: Return a reference to an associative array available
+for user-defined extensions.
+
+
+=head2 The C<SGMLS_Entity> class
+
+All declared entities appear as objects belonging to this class, which
+recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the entity, in
+mixed case.
+
+=item C<type()>: Return a string containing the type of the entity, in
+upper case. Available types are "CDATA", "SDATA", "NDATA" (external
+entities only), "SUBDOC", "PI" (newer versions of B<nsgmls> only), or
+"TEXT" (newer versions of B<nsgmls> only).
+
+=item C<value()>: Return a string containing the value of the entity,
+if it is internal.
+
+=item C<sysid()>: Return a string containing the system identifier of
+the entity (if any), if it is external.
+
+=item C<pubid()>: Return a string containing the public identifier of
+the entity (if any), if it is external.
+
+=item C<filenames()>: Return an array of strings containing any file
+names generated from the identifiers, if the entity is external.
+
+=item C<notation()>: Return the C<SGMLS_Notation> object associated
+with the entity, if it is external.
+
+=item C<data_attributes()>: Return a reference to an associative array
+of data attribute names (in upper case) and the associated
+C<SGMLS_Attribute> objects for the current entity.
+
+=item C<data_attribute_names()>: Return an array of data attribute
+names (in upper case) for the current entity.
+
+=item C<data_attribute(ANAME)>: Return the C<SGMLS_Attribute> object
+for the data attribute named C<ANAME> for the current entity.
+
+=item C<set_data_attribute(ATTRIB)>: Add the C<SGMLS_Attribute> object
+C<ATTRIB> to the current entity, replacing any other data attribute
+with the same name.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright 1994 and 1995 by David Megginson,
+C<dmeggins@aix1.uottawa.ca>. Distributed under the terms of the Gnu
+General Public License (version 2, 1991) -- see the file C<COPYING>
+which is included in the B<SGMLS.pm> distribution.
+
+
+=head1 SEE ALSO:
+
+L<SGMLS::Output> and L<SGMLS::Refs>.
+
+=cut
+
+#
+# Data class for a single SGMLS ESIS output event. The object will
+# keep information about its own current element and, if available,
+# the source file and line where the event appeared.
+#
+# Event types are as follow:
+# Event Data
+# -------------------------------------------------------
+# 'start_element' SGMLS_Element
+# 'end_element' SGMLS_Element
+# 'cdata' string
+# 'sdata' string
+# 're' [none]
+# 'pi' string
+# 'entity' SGMLS_Entity
+# 'start_subdoc' SGMLS_Entity
+# 'end_subdoc' SGMLS_Entity
+# 'conforming' [none]
+#
+package SGMLS_Event;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$type,$data,$parse) = @_;
+ return bless [$type,
+ $data,
+ $parse->file,
+ $parse->line,
+ $parse->element,
+ $parse,
+ {}
+ ];
+}
+ # Accessors.
+sub type { return $_[0]->[0]; }
+sub data { return $_[0]->[1]; }
+sub file { return $_[0]->[2]; }
+sub line { return $_[0]->[3]; }
+sub element { return $_[0]->[4]; }
+sub parse { return $_[0]->[5]; }
+sub ext { return $_[0]->[6]; }
+ # Generate a key for the event.
+sub key {
+ my $self = shift;
+ if (ref($self->data) eq SGMLS_Element ||
+ ref($self->data) eq SGMLS_Entity) {
+ return $self->data->name;
+ } else {
+ return $self->data;
+ }
+}
+ # Look up an entity in the parse.
+sub entity {
+ my ($self,$ename) = (@_);
+ return $self->parse->entity($ename);
+}
+ # Look up a notation in the parse.
+sub notation {
+ my ($self,$nname) = (@_);
+ return $self->parse->notation($nname);
+}
+
+
+#
+# Data class for a single SGML attribute. The object will know its
+# type, and will keep a value unless the type is 'IMPLIED', in which
+# case no meaningful value is available.
+#
+# Attribute types are as follow:
+# Type Value
+# ---------------------------------------
+# IMPLIED [none]
+# CDATA string
+# NOTATION SGMLS_Notation
+# ENTITY SGMLS_Entity
+# TOKEN string
+#
+package SGMLS_Attribute;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$type,$value) = @_;
+ return bless [$name,$type,$value,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub type { return $_[0]->[1]; }
+sub value { return $_[0]->[2]; }
+sub ext { return $_[0]->[3]; }
+ # Return 1 if the value is implied.
+sub is_implied {
+ my $self = shift;
+ return ($self->type eq 'IMPLIED');
+}
+ # Set the attribute's type.
+sub set_type {
+ my ($self,$type) = @_;
+ $self->[1] = $type;
+}
+
+ # Set the attribute's value.
+sub set_value {
+ my ($self,$value) = @_;
+ $self->[2] = $value;
+}
+
+
+#
+# Data class for a single element of an SGML document. The object will not
+# know about its children (data or other elements), but it keeps track of its
+# parent and its attributes.
+#
+package SGMLS_Element;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$parent,$attributes,$parse) = @_;
+ return bless [$name,$parent,$attributes,$parse,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub parent { return $_[0]->[1]; }
+sub parse { return $_[0]->[3]; }
+sub ext { return $_[0]->[4]; }
+
+ # Return the associative array of
+ # attributes, parsing it the first
+ # time through.
+sub attributes {
+ my $self = shift;
+ if (ref($self->[2]) eq 'ARRAY') {
+ my $new = {};
+ foreach (@{$self->[2]}) {
+ /^(\S+) (IMPLIED|CDATA|NOTATION|ENTITY|TOKEN)( (.*))?$/
+ || croak "Bad attribute event data: $_";
+ my ($name,$type,$value) = ($1,$2,$4);
+ if ($type eq 'NOTATION') {
+ $value = $self->parse->notation($value);
+ } elsif ($type eq 'ENTITY') {
+ $value = $self->parse->entity($value);
+ }
+ $new->{$name} =
+ new SGMLS_Attribute($name,$type,$value);
+ }
+ $self->[2] = $new;
+ }
+ return $self->[2];
+}
+ # Return a list of attribute names.
+sub attribute_names {
+ my $self = shift;
+ return keys(%{$self->attributes});
+}
+ # Find an attribute by name.
+sub attribute {
+ my ($self,$aname) = @_;
+ return $self->attributes->{$aname};
+}
+ # Add a new attribute.
+sub set_attribute {
+ my ($self,$attribute) = @_;
+ $self->attributes->{$attribute->name} = $attribute;
+}
+ # Check parent by name.
+sub in {
+ my ($self,$name) = @_;
+ if ($self->parent && $self->parent->name eq $name) {
+ return $self->parent;
+ } else {
+ return '';
+ }
+}
+ # Check ancestors by name.
+sub within {
+ my ($self,$name) = @_;
+ for ($self = $self->parent; $self; $self = $self->parent) {
+ return $self if ($self->name eq $name);
+ }
+ return '';
+}
+
+
+#
+# Data class for an SGML notation. The only information available
+# will be the name, the sysid, and the pubid -- the rest is up to the
+# processing application.
+#
+package SGMLS_Notation;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$sysid,$pubid) = @_;
+ return bless [$name,$sysid,$pubid,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub sysid { return $_[0]->[1]; }
+sub pubid { return $_[0]->[2]; }
+sub ext { return $_[0]->[3]; }
+
+#
+# Data class for a single SGML entity. All entities will have a name
+# and a type. Internal entities will be of type CDATA or SDATA only,
+# and will have a value rather than a notation and sysid/pubid. External
+# CDATA, NDATA, and SDATA entities will always have notations attached,
+# and SUBDOC entities are always external (and will be parsed by SGMLS).
+#
+# Entity types are as follow:
+# Type Internal External
+# -----------------------------------------------------------
+# CDATA x x
+# NDATA x
+# SDATA x x
+# SUBDOC x
+# (newer versions of NSGMLS only:)
+# PI x
+# TEXT x x
+#
+package SGMLS_Entity;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$type,$value,$sysid,$pubid,$filenames,$notation) = @_;
+ return bless [$name,$type,$value,{},$sysid,$pubid,$filenames,$notation,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub type { return $_[0]->[1]; }
+sub value { return $_[0]->[2]; }
+sub data_attributes { return $_[0]->[3]; }
+sub sysid { return $_[0]->[4]; }
+sub pubid { return $_[0]->[5]; }
+sub filenames { return $_[0]->[6]; }
+sub notation { return $_[0]->[7]; }
+sub ext { return $_[0]->[8]; }
+ # Return a list of data-attribute names.
+sub data_attribute_names {
+ my $self = shift;
+ return keys(%{$self->data_attributes});
+}
+ # Find a data attribute by name.
+sub data_attribute {
+ my ($self,$aname) = @_;
+ return $self->data_attributes->{$aname};
+}
+ # Add a new data attribute.
+sub set_data_attribute {
+ my ($self,$data_attribute) = @_;
+ $self->data_attributes()->{$data_attribute->name} = $data_attribute;
+}
+
+
+
+#
+# Data class for a single SGMLS parse. The constructor takes a single
+# argument, a file handle from which the SGMLS ESIS events will be read
+# (it may be a pipe, a fifo, a file, a socket, etc.). It is essential
+# that no two SGMLS objects have the same handle.
+#
+package SGMLS;
+ # Constructor.
+sub new {
+ my ($class,$handle) = @_;
+
+ # Force unqualified filehandles into caller's package
+ my ($package) = caller;
+ $handle =~ s/^[^':]+$/$package\:\:$&/;
+
+ return bless {
+ 'handle' => $handle,
+ 'event_stack' => [],
+ 'current_element' => '',
+ 'current_attributes' => [],
+ 'current_entities' => {},
+ 'entity_stack' => [],
+ 'current_notations' => {},
+ 'notation_stack' => [],
+ 'current_sysid' => '',
+ 'current_pubid' => '',
+ 'current_filenames' => [],
+ 'current_file' => '',
+ 'current_line' => '',
+ 'appinfo' => '',
+ 'ext' => {}
+ };
+}
+ # Accessors.
+sub element { return $_[0]->{'current_element'}; }
+sub file { return $_[0]->{'current_file'}; }
+sub line { return $_[0]->{'current_line'}; }
+sub appinfo { return $_[0]->{'appinfo'}; }
+sub ext { return $_[0]->{'ext'}; }
+
+ # Given its name, look up a notation.
+sub notation {
+ my ($self,$nname) = @_;
+ return $self->{'current_notations'}->{$nname};
+}
+ # Given its name, look up an entity.
+sub entity {
+ my ($self,$ename) = @_;
+ return $self->{'current_entities'}->{$ename};
+}
+
+ # Return the next SGMLS_Event, or ''
+ # if the document has finished.
+sub next_event {
+ my $self = shift;
+ my $handle = $self->{'handle'};
+
+ # If there are any queued up events,
+ # grab them first.
+ if ($#{$self->{event_stack}} >= 0) {
+ return pop @{$self->{event_stack}};
+ }
+
+ dispatch: while (!eof($handle)) {
+
+ my $c = getc($handle);
+ my $data = <$handle>;
+ chop $data;
+
+ ($c eq '(') && do { # start an element
+ $self->{'current_element'} =
+ new SGMLS_Element($data,
+ $self->{'current_element'},
+ $self->{'current_attributes'},
+ $self);
+ $self->{'current_attributes'} = [];
+ return new SGMLS_Event('start_element',
+ $self->{'current_element'},
+ $self);
+ };
+
+ ($c eq ')') && do { # end an element
+ my $old = $self->{'current_element'};
+ $self->{'current_element'} = $self->{'current_element'}->parent;
+ return new SGMLS_Event('end_element',$old,$self);
+ };
+
+ ($c eq '-') && do { # some data
+ my $sdata_flag = 0;
+ my $out = '';
+ while ($data =~ /\\(\\|n|\||[0-7]{1,3})/) {
+ $out .= $`;
+ $data = $';
+ # beginning or end of SDATA
+ if ($1 eq '|') {
+ if ("$out" ne '') {
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event($sdata_flag?'sdata':'cdata',
+ $out,
+ $self));
+ $out = '';
+ }
+ $sdata_flag = !$sdata_flag;
+ # record end
+ } elsif ($1 eq 'n') {
+ if ("$out" ne '') {
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event($sdata_flag?'sdata':'cdata',
+ $out,
+ $self));
+ $out = '';
+ }
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event('re','',$self));
+ } elsif ($1 eq '\\') {
+ $out .= '\\';
+ } else {
+ $out .= chr(oct($1));
+ }
+ }
+ $out .= $data;
+ if ("$out" ne '') {
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event($sdata_flag?'sdata':'cdata',
+ $out,
+ $self));
+ }
+ return $self->next_event;
+ };
+
+ ($c eq '&') && do { # external entity reference
+ return new SGMLS_Event('entity',
+ ($self->{'current_entities'}->{$data}
+ || croak "Unknown external entity: $data\n"),
+ $self);
+ };
+
+ ($c eq '?') && do { # processing instruction
+ return new SGMLS_Event('pi',
+ $data,
+ $self);
+ };
+
+ ($c eq 'A') && do { # attribute declaration
+ # (will parse only on demand)
+ push @{$self->{'current_attributes'}}, $data;
+ next dispatch;
+ };
+
+ ($c eq 'a') && do { # link attribute declaration
+ # NOT YET IMPLEMENTED!
+ next dispatch;
+ };
+
+ ($c eq 'D') && do { # data attribute declaration
+ $data =~ /^(\S+) (\S+) (\S+)( (.*))?$/
+ || croak "Bad data-attribute event data: $data";
+ my ($ename,$aname,$type,$value) = ($1,$2,$3,$5);
+ my $entity = $self->{'current_entities'}->{$ename};
+ my $attribute = new SGMLS_Attribute($aname,$type,$value);
+ $entity->set_data_attribute($attribute);
+ next dispatch;
+ };
+
+ ($c eq 'N') && do { # notation declaration
+ $self->{'current_notations'}->{$data} =
+ new SGMLS_Notation($data,
+ $self->{'current_sysid'},
+ $self->{'current_pubid'});
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ next dispatch;
+ };
+
+ ($c eq 'E') && do { # external entity declaration
+ $data =~ /^(\S+) (\S+) (\S+)$/
+ || croak "Bad external entity event data: $data";
+ my ($name,$type,$nname) = ($1,$2,$3);
+ my $notation = $self->{'current_notations'}->{$nname} if $nname;
+ $self->{'current_entities'}->{$name} =
+ new SGMLS_Entity($name,
+ $type,
+ '',
+ $self->{'current_sysid'},
+ $self->{'current_pubid'},
+ $self->{'current_filenames'},
+ $notation);
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ $self->{'current_filenames'} = [];
+ next dispatch;
+ };
+
+ ($c eq 'I') && do { # internal entity declaration
+ $data =~ /^(\S+) (\S+) (.*)$/
+ || croak "Bad external entity event data: $data";
+ my ($name,$type,$value) = ($1,$2,$3);
+ $self->{'current_entities'}->{$name} =
+ new SGMLS_Entity($name, $type, $value);
+ next dispatch;
+ };
+
+ ($c eq 'T') && do { # external text entity declaration
+ $self->{'current_entities'}->{$data} =
+ new SGMLS_Entity($data,
+ 'TEXT',
+ '',
+ $self->{'current_sysid'},
+ $self->{'current_pubid'},
+ $self->{'current_filenames'},
+ '');
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ $self->{'current_filenames'} = [];
+ next dispatch;
+ };
+
+ ($c eq 'S') && do { # subdocument entity declaration
+ $self->{'current_entities'}->{$data} =
+ new SGMLS_Entity($data,
+ 'SUBDOC',
+ '',
+ $self->{'current_sysid'},
+ $self->{'current_pubid'},
+ $self->{'current_filenames'},
+ '');
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ $self->{'current_filenames'} = [];
+ next dispatch;
+ };
+
+ ($c eq 's') && do { # system id
+ $self->{'current_sysid'} = $data;
+ next dispatch;
+ };
+
+ ($c eq 'p') && do { # public id
+ $self->{'current_pubid'} = $data;
+ next dispatch;
+ };
+
+ ($c eq 'f') && do { # generated filename
+ push @{$self->{'current_filenames'}}, $data;
+ next dispatch;
+ };
+
+ ($c eq '{') && do { # begin subdocument entity
+ my $subdoc = ($self->{'current_entities'}->{$data}||
+ croak "Unknown SUBDOC entity $data\n");
+ push @{$self->{'notation_stack'}}, $self->{'current_notations'};
+ push @{$self->{'entity_stack'}}, $self->{'current_entities'};
+ $self->{'current_notations'} = {};
+ $self->{'current_entities'} = {};
+ return new SGMLS_Event('start_subdoc',
+ $subdoc,
+ $self);
+ };
+
+ ($c eq '}') && do { # end subdocument entity
+ $self->{'current_notations'} = pop @{$self->{'notation_stack'}};
+ $self->{'current_entities'} = pop @{$self->{'entity_stack'}};
+ return new SGMLS_Event('end_subdoc',
+ ($self->{'current_entities'}->{$data} ||
+ croak "Unknown SUBDOC entity $data\n"),
+ $self);
+ };
+
+ ($c eq 'L') && do { # line number (and file name)
+ $data =~ /^(\d+)( (.*))?$/;
+ $self->{'current_line'} = $1;
+ $self->{'current_file'} = $3 if $3;
+ next dispatch;
+ };
+
+ ($c eq '#') && do { # APPINFO parameter
+ $self->{'appinfo'} = $data;
+ next dispatch;
+ };
+
+ ($c eq 'C') && do { # document is conforming
+ return new SGMLS_Event('conforming','',$self);
+ };
+ }
+ return '';
+}
+
+1;
+
+########################################################################
+# Local Variables:
+# mode: perl
+# End:
+########################################################################
diff --git a/info/examples/lwc/ch7/SGMLS/Output.pm b/info/examples/lwc/ch7/SGMLS/Output.pm
new file mode 100644
index 0000000000..4758bfa80f
--- /dev/null
+++ b/info/examples/lwc/ch7/SGMLS/Output.pm
@@ -0,0 +1,225 @@
+package SGMLS::Output;
+use Carp;
+
+use Exporter;
+@ISA = Exporter;
+@EXPORT = qw(output push_output pop_output);
+
+$version = '$Id: Output.pm,v 1.6 1995/12/05 12:21:51 david Exp $';
+
+=head1 NAME
+
+SGMLS::Output - Stack-based Output Procedures
+
+=head1 SYNOPSIS
+
+ use SGMLS::Output;
+
+To print a string to the current output destination:
+
+ output($data);
+
+To push a new output level to the filehandle DATA:
+
+ push_output('handle',DATA);
+
+To push a new output level to the file "foo.data" (which will be
+opened and closed automatically):
+
+ push_output('file','foo.data');
+
+To push a new output level to a pipe to the shell command "sort":
+
+ push_output('pipe','sort');
+
+To push a new output level I<appending> to the file "foo.data":
+
+ push_output('append','foo.data');
+
+To push a new output level to an empty string:
+
+ push_output('string');
+
+To push a new output level appending to the string "David is ":
+
+ push_output('string',"David is ");
+
+To push a new output level to The Great Beyond:
+
+ push_output('nul');
+
+To revert to the previous output level:
+
+ pop_output();
+
+To revert to the previous output level, returning the contents of an
+output string:
+
+ $data = pop_output();
+
+=head1 DESCRIPTION
+
+This library allows redirectable, stack-based output to files, pipes,
+handles, strings, or nul. It is especially useful for packages like
+L<SGMLS>, since handlers for individual B<SGML> elements can
+temporarily change and restore the default output destination. It is
+also particularly useful for capturing the contents of an element (and
+its sub-elements) in a string.
+
+Example:
+
+ sgmls('<title>', sub{ push_output('string'); });
+ sgmls('</title>', sub{ $title = pop_output(); });
+
+In between, anything sent to B<output> (such as CDATA) will be
+accumulated in the string returned from B<pop_output()>.
+
+Example:
+
+ sgmls('<tei.header>', sub { push_output('nul'); });
+ sgmls('</tei.header>', sub { pop_output(); });
+
+All output will be ignored until the header has finished.
+
+
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright 1994 and 1995 by David Megginson,
+C<dmeggins@aix1.uottawa.ca>. Distributed under the terms of the Gnu
+General Public License (version 2, 1991) -- see the file C<COPYING>
+which is included in the B<SGMLS.pm> distribution.
+
+
+=head1 SEE ALSO:
+
+L<SGMLS>.
+
+=cut
+
+#
+# Anonymous subroutines for handling different types of references.
+#
+$output_handle_sub = sub {
+ print $current_output_data @_;
+};
+
+$output_file_sub = sub {
+ print $current_output_data @_;
+};
+
+$output_string_sub = sub {
+ $current_output_data .= shift;
+ foreach (@_) {
+ $current_output_data .= $, . $_;
+ }
+ $current_output_data .= $\;
+};
+
+$output_nul_sub = sub {};
+
+#
+# Status variables
+#
+$current_output_type = 'handle';
+$current_output_data = STDOUT;
+$current_output_sub = $output_handle_sub;
+@output_stack = qw();
+
+#
+# Externally-visible functions
+#
+
+ # Send data to the output.
+sub output {
+ &{$current_output_sub}(@_);
+}
+
+ # Push a new output destination.
+sub push_output {
+ my ($type,$data) = @_;
+ push @output_stack, [$current_output_type,$current_output_data,
+ $current_output_sub];
+ SWITCH: {
+ $type eq 'handle' && do {
+ # Force unqualified filehandles into caller's package
+ my ($package) = caller;
+ $data =~ s/^[^':]+$/$package\:\:$&/;
+
+ $current_output_sub = $output_handle_sub;
+ $current_output_type = 'handle';
+ $current_output_data = $data;
+ last SWITCH;
+ };
+ $type eq 'file' && do {
+ $current_output_sub = $output_file_sub;
+ my $handle = new_handle();
+ open($handle,">$data") || croak "Cannot create file $data.\n";
+ $current_output_type = 'file';
+ $current_output_data = $handle;
+ last SWITCH;
+ };
+ $type eq 'pipe' && do {
+ $current_output_sub = $output_file_sub;
+ my $handle = new_handle();
+ open($handle,"|$data") || croak "Cannot open pipe to $data.\n";
+ $current_output_type = 'file';
+ $current_output_data = $handle;
+ last SWITCH;
+ };
+ $type eq 'append' && do {
+ $current_output_sub = $output_file_sub;
+ my $handle = new_handle();
+ open($handle,">>$data") || croak "Cannot append to file $data.\n";
+ $current_output_type = 'file';
+ $current_output_data = $handle;
+ last SWITCH;
+ };
+ $type eq 'string' && do {
+ $current_output_sub = $output_string_sub;
+ $current_output_type = 'string';
+ $current_output_data = $data;
+ last SWITCH;
+ };
+ $type eq 'nul' && do {
+ $current_output_sub = $output_nul_sub;
+ $current_output_type = 'nul';
+ $current_output_data = '';
+ last SWITCH;
+ };
+ croak "Unknown output type: $type.\n";
+ }
+}
+
+ # Pop the current output destination.
+sub pop_output {
+ my ($old_type,$old_data) = ($current_output_type,$current_output_data);
+ ($current_output_type,$current_output_data,$current_output_sub) =
+ @{pop @output_stack};
+ SWITCH: {
+ $old_type eq 'handle' && do {
+ return $old_data;
+ };
+ $old_type eq 'file' && do {
+ close($old_data);
+ return '';
+ };
+ $old_type eq 'string' && do {
+ return $old_data;
+ };
+ $old_type eq 'nul' && do {
+ return '';
+ };
+ croak "Unknown output type: $type.\n";
+ }
+}
+
+#
+# Local Utility functions.
+#
+$new_handle_counter = 1;
+
+sub new_handle {
+ return "IOHandle" . $new_handle_counter++;
+}
+
+1;
diff --git a/info/examples/lwc/ch7/SGMLS/Refs.pm b/info/examples/lwc/ch7/SGMLS/Refs.pm
new file mode 100644
index 0000000000..3e3f563770
--- /dev/null
+++ b/info/examples/lwc/ch7/SGMLS/Refs.pm
@@ -0,0 +1,216 @@
+package SGMLS::Refs;
+
+use Carp;
+
+$version = '$Id: Refs.pm,v 1.5 1995/12/03 21:28:36 david Exp $';
+
+=head1 NAME
+
+SGMLS::Refs
+
+=head1 SYNOPSIS
+
+ use SGMLS::Refs;
+
+To create a new reference-manager object using the file "foo.refs":
+
+ my $refs = new SGMLS::Refs("foo.refs");
+
+To create a new reference-manager object using the file "foo.refs" and
+logging changes to the file "foo.log":
+
+ my $refs = new SGMLS::Refs("foo.refs","foo.log");
+
+To record a reference:
+
+ $refs->put("document title",$title);
+
+To retrieve a reference:
+
+ $title = $refs->get("document title");
+
+To return the number of references changed since the last run:
+
+ $num = $refs->changed;
+
+To print a LaTeX-like warning if any references have changed:
+
+ $refs->warn;
+
+=head1 DESCRIPTION
+
+This library can be used together with the B<SGMLS> package to keep
+track of forward references from one run to another, like the B<LaTeX>
+C<.aux> files. Each reference manager is an object which reads and
+then rewrites a file of perl source, with the file name provided by
+the caller.
+
+Example:
+
+ # Start up the reference manager before the parse.
+ sgml('start', sub { $refs = new SGMLS::Refs("foo.refs"); });
+
+ # Warn about any changed references at the end.
+ sgml('end', sub { $refs->warn; });
+
+ # Look up the title from the last parse, if available.
+ sgml('<div>', sub {
+ my $element = shift;
+ my $id = $element->attribute(ID)->value;
+ my $title = $refs->get("title:$id") || "[no title available]";
+
+ $current_div_id = $id;
+
+ output "\\section{$title}\n\n";
+ });
+
+
+ # Save the title for the next parse.
+ sgml('<head>', sub { push_output('string'); });
+ sgml('</head>', sub {
+ my $title = pop_output();
+ my $id = $current_div_id;
+
+ $refs->put("title:$id",$title);
+ });
+
+
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright 1994 and 1995 by David Megginson,
+C<dmeggins@aix1.uottawa.ca>. Distributed under the terms of the Gnu
+General Public License (version 2, 1991) -- see the file C<COPYING>
+which is included in the B<SGMLS.pm> distribution.
+
+
+=head1 SEE ALSO:
+
+L<SGMLS>, L<SGMLS::Output>.
+
+=cut
+
+#
+# Create a new instance of a reference manager. The first argument is
+# the filename for the database, and the second (if present) is a
+# filename for logging changes.
+#
+sub new {
+ my ($class,$filename,$logname) = (@_);
+ my $self = {};
+ my $handle = generate_handle();
+ my $loghandle = generate_handle() if $logname;
+ my $oldRS = $/; # Save old record separator.
+
+ # Read the current contents of the reference file (if any).
+ if (open($handle,"<$filename")) {
+ $/ = 0777;
+ $self->{'refs'} = eval <$handle> || {};
+ close $handle;
+ } else {
+ $self->{'refs'} = {};
+ }
+
+ # Open the reference file.
+ open($handle,">$filename") || croak $@;
+
+ # Open the log file, if any.
+ if ($logname) {
+ open($loghandle,">$logname") || croak $@;
+ }
+
+ # Note pertinent information.
+ $self->{'change_count'} = 0;
+ $self->{'handle'} = $handle;
+ $self->{'loghandle'} = $loghandle;
+ $self->{'filename'} = $filename;
+ $self->{'logname'} = $logname;
+
+ $/ = $oldRS; # Restore old record separator.
+ return bless $self;
+}
+
+#
+# Set a reference's value. If the value is unchanged, don't do anything;
+# otherwise, note the change by counting it and (optionally) logging it
+# to the file handle provided when the object was created.
+#
+sub put {
+ my ($self,$key,$value) = (@_);
+ my $loghandle = $self->{'loghandle'};
+ my $oldvalue = $self->{'refs'}->{$key};
+
+ if ($oldvalue ne $value) {
+ $self->{'change_count'}++;
+ if ($loghandle) {
+ print $loghandle "\"$key\" changed from " .
+
+ "\"$oldvalue\" to \"$value\".\n";
+ }
+ $self->{'refs'}->{$key} = $value;
+ }
+
+ return $oldvalue;
+}
+
+#
+# Grab the value of a reference.
+#
+sub get {
+ my ($self,$key) = (@_);
+
+ return $self->{'refs'}->{$key};
+}
+
+#
+# Return the number of changed references.
+#
+sub changed {
+ my $self = shift;
+ return $self->{'changed_count'};
+}
+
+#
+# Print a warning if any references have
+# changed (a la LaTeX -- so that the user knows that another pass is
+# necessary). Return 1 if a warning has been printed, or 0 if it
+# was unnecessary.
+#
+sub warn {
+ my $self = shift;
+ my $count = $self->{'change_count'};
+ my $filename = $self->{'filename'};
+ my $plural = "references have";
+
+ $plural = "reference has" if $count == 1;
+ if ($count > 0) {
+ warn "SGMLS::Refs ($filename): $count $plural changed.\n";
+ return 1;
+ }
+ return 0;
+}
+
+sub DESTROY {
+ my $self = shift;
+ my $handle = $self->{'handle'};
+
+ close $self->{'loghandle'};
+
+ print $handle "{\n";
+ foreach $key (keys %{$self->{'refs'}}) {
+ my $value = $self->{'refs'}->{$key};
+ $key =~ s/\\/\\\\/g;
+ $key =~ s/'/\\'/g;
+ $value =~ s/\\/\\\\/g;
+ $value =~ s/'/\\'/g;
+ print $handle " '$key' => '$value',\n";
+ }
+ print $handle " '' => ''\n}\n";
+}
+
+$handle_counter = 1;
+sub generate_handle {
+ return "Handle" . $handle_counter++;
+}
+
+1;
+
diff --git a/info/examples/lwc/ch7/SGMLS/SGMLS.pm b/info/examples/lwc/ch7/SGMLS/SGMLS.pm
new file mode 100644
index 0000000000..b29395eed3
--- /dev/null
+++ b/info/examples/lwc/ch7/SGMLS/SGMLS.pm
@@ -0,0 +1,893 @@
+package SGMLS;
+use Carp;
+
+$version = '$Revision: 1.14 $';
+
+=head1 NAME
+
+SGMLS - class for postprocessing the output from the B<sgmls> and
+B<nsgmls> parsers.
+
+=head1 SYNOPSIS
+
+ use SGMLS;
+
+ my $parse = new SGMLS(STDIN);
+
+ my $event = $parse->next_event;
+ while ($event) {
+
+ SWITCH: {
+
+ ($event->type eq 'start_element') && do {
+ my $element = $event->data; # An object of class SGMLS_Element
+ [[your code for the beginning of an element]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'end_element') && do {
+ my $element = $event->data; # An object of class SGMLS_Element
+ [[your code for the end of an element]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'cdata') && do {
+ my $cdata = $event->data; # A string
+ [[your code for character data]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'sdata') && do {
+ my $sdata = $event->data; # A string
+ [[your code for system data]]
+ last SWITCH;
+ };
+
+ ($event->type eq 're') && do {
+ [[your code for a record end]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'pi') && do {
+ my $pi = $event->data; # A string
+ [[your code for a processing instruction]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'entity') && do {
+ my $entity = $event->data; # An object of class SGMLS_Entity
+ [[your code for an external entity]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'start_subdoc') && do {
+ my $entity = $event->data; # An object of class SGMLS_Entity
+ [[your code for the beginning of a subdoc entity]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'end_subdoc') && do {
+ my $entity = $event->data; # An object of class SGMLS_Entity
+ [[your code for the end of a subdoc entity]]
+ last SWITCH;
+ };
+
+ ($event->type eq 'conforming') && do {
+ [[your code for a conforming document]]
+ last SWITCH;
+ };
+
+ die "Internal error: unknown event type " . $event->type . "\n";
+ }
+
+ $event = $parse->next_event;
+ }
+
+=head1 DESCRIPTION
+
+The B<SGMLS> package consists of several related classes: see
+L<"SGMLS">, L<"SGMLS_Event">, L<"SGMLS_Element">,
+L<"SGMLS_Attribute">, L<"SGMLS_Notation">, and L<"SGMLS_Entity">. All
+of these classes are available when you specify
+
+ use SGMLS;
+
+Generally, the only object which you will create explicitly will
+belong to the C<SGMLS> class; all of the others will then be created
+automatically for you over the course of the parse. Much fuller
+documentation is available in the C<.sgml> files in the C<DOC/>
+directory of the C<SGMLS.pm> distribution.
+
+=head2 The C<SGMLS> class
+
+This class holds a single parse. When you create an instance of it,
+you specify a file handle as an argument (if you are reading the
+output of B<sgmls> or B<nsgmls> from a pipe, the file handle will
+ordinarily be C<STDIN>):
+
+ my $parse = new SGMLS(STDIN);
+
+The most important method for this class is C<next_event>, which reads
+and returns the next major event from the input stream. It is
+important to note that the C<SGMLS> class deals with most B<ESIS>
+events itself: attributes and entity definitions, for example, are
+collected and stored automatically and invisibly to the user. The
+following list contains all of the methods for the C<SGMLS> class:
+
+=item C<next_event()>: Return an C<SGMLS_Event> object containing the
+next major event from the SGML parse.
+
+=item C<element()>: Return an C<SGMLS_Element> object containing the
+current element in the document.
+
+=item C<file()>: Return a string containing the name of the current
+SGML source file (this will work only if the C<-l> option was given to
+B<sgmls> or B<nsgmls>).
+
+=item C<line()>: Return a string containing the current line number
+from the source file (this will work only if the C<-l> option was
+given to B<sgmls> or B<nsgmls>).
+
+=item C<appinfo()>: Return a string containing the C<APPINFO>
+parameter (if any) from the SGML declaration.
+
+=item C<notation(NNAME)>: Return an C<SGMLS_Notation> object
+representing the notation named C<NNAME>. With newer versions of
+B<nsgmls>, all notations are available; otherwise, only the notations
+which are actually used will be available.
+
+=item C<entity(ENAME)>: Return an C<SGMLS_Entity> object representing
+the entity named C<ENAME>. With newer versions of B<nsgmls>, all
+entities are available; otherwise, only external data entities and
+internal entities used as attribute values will be available.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Event> class
+
+This class holds a single major event, as generated by the
+C<next_event> method in the C<SGMLS> class. It uses the following
+methods:
+
+=item C<type()>: Return a string describing the type of event:
+"start_element", "end_element", "cdata", "sdata", "re", "pi",
+"entity", "start_subdoc", "end_subdoc", and "conforming". See
+L<"SYNOPSIS">, above, for the values associated with each of these.
+
+=item C<data()>: Return the data associated with the current event (if
+any). For "start_element" and "end_element", returns an
+C<SGMLS_ELement> object; for "entity", "start_subdoc", and
+"end_subdoc", returns an C<SGMLS_Entity> object; for "cdata", "sdata",
+and "pi", returns a string; and for "re" and "conforming", returns the
+empty string. See L<"SYNOPSIS">, above, for an example of this
+method's use.
+
+=item C<key()>: Return a string key to the event, such as an element
+or entity name (otherwise, the same as C<data()>).
+
+=item C<file()>: Return the current file name, as in the C<SGMLS>
+class.
+
+=item C<line()>: Return the current line number, as in the C<SGMLS>
+class.
+
+=item C<element()>: Return the current element, as in the C<SGMLS>
+class.
+
+=item C<parse()>: Return the C<SGMLS> object which generated the
+event.
+
+=item C<entity(ENAME)>: Look up an entity, as in the C<SGMLS> class.
+
+=item C<notation(ENAME)>: Look up a notation, as in the C<SGMLS>
+class.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Element> class
+
+This class is used for elements, and contains all associated
+information (such as the element's attributes). It recognises the
+following methods:
+
+=item C<name()>: Return a string containing the name, or Generic
+Identifier, of the element, in upper case.
+
+=item C<parent()>: Return the C<SGMLS_Element> object for the
+element's parent (if any).
+
+=item C<parse()>: Return the C<SGMLS> object for the current parse.
+
+=item C<attributes()>: Return a reference to an associative array of
+attribute names and C<SGMLS_Attribute> structures. Attribute names
+will be all in upper case.
+
+=item C<attribute_names()>: Return an array of strings containing the
+names of all attributes defined for the current element, in upper
+case.
+
+=item C<attribute(ANAME)>: Return the C<SGMLS_Attribute> structure for
+the attribute C<ANAME>.
+
+=item C<set_attribute(ATTRIB)>: Add the C<SGMLS_Attribute> object
+C<ATTRIB> to the current element, replacing any other attribute
+structure with the same name.
+
+=item C<in(GI)>: Return C<true> (ie. 1) if the string C<GI> is the
+name of the current element's parent, or C<false> (ie. 0) if it is
+not.
+
+=item C<within(GI)>: Return C<true> (ie. 1) if the string C<GI> is the
+name of any of the ancestors of the current element, or C<false>
+(ie. 0) if it is not.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Attribute> class
+
+Each instance of an attribute for each C<SGMLS_Element> is an object
+belonging to this class, which recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the current
+attribute, all in upper case.
+
+=item C<type()>: Return a string containing the type of the current
+attribute, all in upper case. Available types are "IMPLIED", "CDATA",
+"NOTATION", "ENTITY", and "TOKEN".
+
+=item C<value()>: Return the value of the current attribute, if any.
+This will be an empty string if the type is "IMPLIED", a string of
+some sort if the type is "CDATA" or "TOKEN" (if it is "TOKEN", you may
+want to split the string into a series of separate tokens), an
+C<SGMLS_Notation> object if the type is "NOTATION", or an
+C<SGMLS_Entity> object if the type is "ENTITY". Note that if the
+value is "CDATA", it will I<not> have escape sequences for 8-bit
+characters, record ends, or SDATA processed -- that will be your
+responsibility.
+
+=item C<is_implied()>: Return C<true> (ie. 1) if the value of the
+attribute is implied, or C<false> (ie. 0) if it is specified in the
+document.
+
+=item C<set_type(TYPE)>: Change the type of the attribute to the
+string C<TYPE> (which should be all in upper case). Available types
+are "IMPLIED", "CDATA", "NOTATION", "ENTITY", and "TOKEN".
+
+=item C<set_value(VALUE)>: Change the value of the attribute to
+C<VALUE>, which may be a string, an C<SGMLS_Entity> object, or an
+C<SGMLS_Notation> subject, depending on the attribute's type.
+
+=item C<ext()>: Return a reference to an associative array available
+for user-defined extensions.
+
+
+=head2 The C<SGMLS_Notation> class
+
+All declared notations appear as objects belonging to this class,
+which recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the notation.
+
+=item C<sysid()>: Return a string containing the system identifier of
+the notation, if any.
+
+=item C<pubid()>: Return a string containing the public identifier of
+the notation, if any.
+
+=item C<ext()>: Return a reference to an associative array available
+for user-defined extensions.
+
+
+=head2 The C<SGMLS_Entity> class
+
+All declared entities appear as objects belonging to this class, which
+recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the entity, in
+mixed case.
+
+=item C<type()>: Return a string containing the type of the entity, in
+upper case. Available types are "CDATA", "SDATA", "NDATA" (external
+entities only), "SUBDOC", "PI" (newer versions of B<nsgmls> only), or
+"TEXT" (newer versions of B<nsgmls> only).
+
+=item C<value()>: Return a string containing the value of the entity,
+if it is internal.
+
+=item C<sysid()>: Return a string containing the system identifier of
+the entity (if any), if it is external.
+
+=item C<pubid()>: Return a string containing the public identifier of
+the entity (if any), if it is external.
+
+=item C<filenames()>: Return an array of strings containing any file
+names generated from the identifiers, if the entity is external.
+
+=item C<notation()>: Return the C<SGMLS_Notation> object associated
+with the entity, if it is external.
+
+=item C<data_attributes()>: Return a reference to an associative array
+of data attribute names (in upper case) and the associated
+C<SGMLS_Attribute> objects for the current entity.
+
+=item C<data_attribute_names()>: Return an array of data attribute
+names (in upper case) for the current entity.
+
+=item C<data_attribute(ANAME)>: Return the C<SGMLS_Attribute> object
+for the data attribute named C<ANAME> for the current entity.
+
+=item C<set_data_attribute(ATTRIB)>: Add the C<SGMLS_Attribute> object
+C<ATTRIB> to the current entity, replacing any other data attribute
+with the same name.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright 1994 and 1995 by David Megginson,
+C<dmeggins@aix1.uottawa.ca>. Distributed under the terms of the Gnu
+General Public License (version 2, 1991) -- see the file C<COPYING>
+which is included in the B<SGMLS.pm> distribution.
+
+
+=head1 SEE ALSO:
+
+L<SGMLS::Output> and L<SGMLS::Refs>.
+
+=cut
+
+#
+# Data class for a single SGMLS ESIS output event. The object will
+# keep information about its own current element and, if available,
+# the source file and line where the event appeared.
+#
+# Event types are as follow:
+# Event Data
+# -------------------------------------------------------
+# 'start_element' SGMLS_Element
+# 'end_element' SGMLS_Element
+# 'cdata' string
+# 'sdata' string
+# 're' [none]
+# 'pi' string
+# 'entity' SGMLS_Entity
+# 'start_subdoc' SGMLS_Entity
+# 'end_subdoc' SGMLS_Entity
+# 'conforming' [none]
+#
+package SGMLS_Event;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$type,$data,$parse) = @_;
+ return bless [$type,
+ $data,
+ $parse->file,
+ $parse->line,
+ $parse->element,
+ $parse,
+ {}
+ ];
+}
+ # Accessors.
+sub type { return $_[0]->[0]; }
+sub data { return $_[0]->[1]; }
+sub file { return $_[0]->[2]; }
+sub line { return $_[0]->[3]; }
+sub element { return $_[0]->[4]; }
+sub parse { return $_[0]->[5]; }
+sub ext { return $_[0]->[6]; }
+ # Generate a key for the event.
+sub key {
+ my $self = shift;
+ if (ref($self->data) eq SGMLS_Element ||
+ ref($self->data) eq SGMLS_Entity) {
+ return $self->data->name;
+ } else {
+ return $self->data;
+ }
+}
+ # Look up an entity in the parse.
+sub entity {
+ my ($self,$ename) = (@_);
+ return $self->parse->entity($ename);
+}
+ # Look up a notation in the parse.
+sub notation {
+ my ($self,$nname) = (@_);
+ return $self->parse->notation($nname);
+}
+
+
+#
+# Data class for a single SGML attribute. The object will know its
+# type, and will keep a value unless the type is 'IMPLIED', in which
+# case no meaningful value is available.
+#
+# Attribute types are as follow:
+# Type Value
+# ---------------------------------------
+# IMPLIED [none]
+# CDATA string
+# NOTATION SGMLS_Notation
+# ENTITY SGMLS_Entity
+# TOKEN string
+#
+package SGMLS_Attribute;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$type,$value) = @_;
+ return bless [$name,$type,$value,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub type { return $_[0]->[1]; }
+sub value { return $_[0]->[2]; }
+sub ext { return $_[0]->[3]; }
+ # Return 1 if the value is implied.
+sub is_implied {
+ my $self = shift;
+ return ($self->type eq 'IMPLIED');
+}
+ # Set the attribute's type.
+sub set_type {
+ my ($self,$type) = @_;
+ $self->[1] = $type;
+}
+
+ # Set the attribute's value.
+sub set_value {
+ my ($self,$value) = @_;
+ $self->[2] = $value;
+}
+
+
+#
+# Data class for a single element of an SGML document. The object will not
+# know about its children (data or other elements), but it keeps track of its
+# parent and its attributes.
+#
+package SGMLS_Element;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$parent,$attributes,$parse) = @_;
+ return bless [$name,$parent,$attributes,$parse,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub parent { return $_[0]->[1]; }
+sub parse { return $_[0]->[3]; }
+sub ext { return $_[0]->[4]; }
+
+ # Return the associative array of
+ # attributes, parsing it the first
+ # time through.
+sub attributes {
+ my $self = shift;
+ if (ref($self->[2]) eq 'ARRAY') {
+ my $new = {};
+ foreach (@{$self->[2]}) {
+ /^(\S+) (IMPLIED|CDATA|NOTATION|ENTITY|TOKEN)( (.*))?$/
+ || croak "Bad attribute event data: $_";
+ my ($name,$type,$value) = ($1,$2,$4);
+ if ($type eq 'NOTATION') {
+ $value = $self->parse->notation($value);
+ } elsif ($type eq 'ENTITY') {
+ $value = $self->parse->entity($value);
+ }
+ $new->{$name} =
+ new SGMLS_Attribute($name,$type,$value);
+ }
+ $self->[2] = $new;
+ }
+ return $self->[2];
+}
+ # Return a list of attribute names.
+sub attribute_names {
+ my $self = shift;
+ return keys(%{$self->attributes});
+}
+ # Find an attribute by name.
+sub attribute {
+ my ($self,$aname) = @_;
+ return $self->attributes->{$aname};
+}
+ # Add a new attribute.
+sub set_attribute {
+ my ($self,$attribute) = @_;
+ $self->attributes->{$attribute->name} = $attribute;
+}
+ # Check parent by name.
+sub in {
+ my ($self,$name) = @_;
+ if ($self->parent && $self->parent->name eq $name) {
+ return $self->parent;
+ } else {
+ return '';
+ }
+}
+ # Check ancestors by name.
+sub within {
+ my ($self,$name) = @_;
+ for ($self = $self->parent; $self; $self = $self->parent) {
+ return $self if ($self->name eq $name);
+ }
+ return '';
+}
+
+
+#
+# Data class for an SGML notation. The only information available
+# will be the name, the sysid, and the pubid -- the rest is up to the
+# processing application.
+#
+package SGMLS_Notation;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$sysid,$pubid) = @_;
+ return bless [$name,$sysid,$pubid,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub sysid { return $_[0]->[1]; }
+sub pubid { return $_[0]->[2]; }
+sub ext { return $_[0]->[3]; }
+
+#
+# Data class for a single SGML entity. All entities will have a name
+# and a type. Internal entities will be of type CDATA or SDATA only,
+# and will have a value rather than a notation and sysid/pubid. External
+# CDATA, NDATA, and SDATA entities will always have notations attached,
+# and SUBDOC entities are always external (and will be parsed by SGMLS).
+#
+# Entity types are as follow:
+# Type Internal External
+# -----------------------------------------------------------
+# CDATA x x
+# NDATA x
+# SDATA x x
+# SUBDOC x
+# (newer versions of NSGMLS only:)
+# PI x
+# TEXT x x
+#
+package SGMLS_Entity;
+use Carp;
+ # Constructor.
+sub new {
+ my ($class,$name,$type,$value,$sysid,$pubid,$filenames,$notation) = @_;
+ return bless [$name,$type,$value,{},$sysid,$pubid,$filenames,$notation,{}];
+}
+ # Accessors.
+sub name { return $_[0]->[0]; }
+sub type { return $_[0]->[1]; }
+sub value { return $_[0]->[2]; }
+sub data_attributes { return $_[0]->[3]; }
+sub sysid { return $_[0]->[4]; }
+sub pubid { return $_[0]->[5]; }
+sub filenames { return $_[0]->[6]; }
+sub notation { return $_[0]->[7]; }
+sub ext { return $_[0]->[8]; }
+ # Return a list of data-attribute names.
+sub data_attribute_names {
+ my $self = shift;
+ return keys(%{$self->data_attributes});
+}
+ # Find a data attribute by name.
+sub data_attribute {
+ my ($self,$aname) = @_;
+ return $self->data_attributes->{$aname};
+}
+ # Add a new data attribute.
+sub set_data_attribute {
+ my ($self,$data_attribute) = @_;
+ $self->data_attributes()->{$data_attribute->name} = $data_attribute;
+}
+
+
+
+#
+# Data class for a single SGMLS parse. The constructor takes a single
+# argument, a file handle from which the SGMLS ESIS events will be read
+# (it may be a pipe, a fifo, a file, a socket, etc.). It is essential
+# that no two SGMLS objects have the same handle.
+#
+package SGMLS;
+ # Constructor.
+sub new {
+ my ($class,$handle) = @_;
+
+ # Force unqualified filehandles into caller's package
+ my ($package) = caller;
+ $handle =~ s/^[^':]+$/$package\:\:$&/;
+
+ return bless {
+ 'handle' => $handle,
+ 'event_stack' => [],
+ 'current_element' => '',
+ 'current_attributes' => [],
+ 'current_entities' => {},
+ 'entity_stack' => [],
+ 'current_notations' => {},
+ 'notation_stack' => [],
+ 'current_sysid' => '',
+ 'current_pubid' => '',
+ 'current_filenames' => [],
+ 'current_file' => '',
+ 'current_line' => '',
+ 'appinfo' => '',
+ 'ext' => {}
+ };
+}
+ # Accessors.
+sub element { return $_[0]->{'current_element'}; }
+sub file { return $_[0]->{'current_file'}; }
+sub line { return $_[0]->{'current_line'}; }
+sub appinfo { return $_[0]->{'appinfo'}; }
+sub ext { return $_[0]->{'ext'}; }
+
+ # Given its name, look up a notation.
+sub notation {
+ my ($self,$nname) = @_;
+ return $self->{'current_notations'}->{$nname};
+}
+ # Given its name, look up an entity.
+sub entity {
+ my ($self,$ename) = @_;
+ return $self->{'current_entities'}->{$ename};
+}
+
+ # Return the next SGMLS_Event, or ''
+ # if the document has finished.
+sub next_event {
+ my $self = shift;
+ my $handle = $self->{'handle'};
+
+ # If there are any queued up events,
+ # grab them first.
+ if ($#{$self->{event_stack}} >= 0) {
+ return pop @{$self->{event_stack}};
+ }
+
+ dispatch: while (!eof($handle)) {
+
+ my $c = getc($handle);
+ my $data = <$handle>;
+ chop $data;
+
+ ($c eq '(') && do { # start an element
+ $self->{'current_element'} =
+ new SGMLS_Element($data,
+ $self->{'current_element'},
+ $self->{'current_attributes'},
+ $self);
+ $self->{'current_attributes'} = [];
+ return new SGMLS_Event('start_element',
+ $self->{'current_element'},
+ $self);
+ };
+
+ ($c eq ')') && do { # end an element
+ my $old = $self->{'current_element'};
+ $self->{'current_element'} = $self->{'current_element'}->parent;
+ return new SGMLS_Event('end_element',$old,$self);
+ };
+
+ ($c eq '-') && do { # some data
+ my $sdata_flag = 0;
+ my $out = '';
+ while ($data =~ /\\(\\|n|\||[0-7]{1,3})/) {
+ $out .= $`;
+ $data = $';
+ # beginning or end of SDATA
+ if ($1 eq '|') {
+ if ("$out" ne '') {
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event($sdata_flag?'sdata':'cdata',
+ $out,
+ $self));
+ $out = '';
+ }
+ $sdata_flag = !$sdata_flag;
+ # record end
+ } elsif ($1 eq 'n') {
+ if ("$out" ne '') {
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event($sdata_flag?'sdata':'cdata',
+ $out,
+ $self));
+ $out = '';
+ }
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event('re','',$self));
+ } elsif ($1 eq '\\') {
+ $out .= '\\';
+ } else {
+ $out .= chr(oct($1));
+ }
+ }
+ $out .= $data;
+ if ("$out" ne '') {
+ unshift(@{$self->{'event_stack'}},
+ new SGMLS_Event($sdata_flag?'sdata':'cdata',
+ $out,
+ $self));
+ }
+ return $self->next_event;
+ };
+
+ ($c eq '&') && do { # external entity reference
+ return new SGMLS_Event('entity',
+ ($self->{'current_entities'}->{$data}
+ || croak "Unknown external entity: $data\n"),
+ $self);
+ };
+
+ ($c eq '?') && do { # processing instruction
+ return new SGMLS_Event('pi',
+ $data,
+ $self);
+ };
+
+ ($c eq 'A') && do { # attribute declaration
+ # (will parse only on demand)
+ push @{$self->{'current_attributes'}}, $data;
+ next dispatch;
+ };
+
+ ($c eq 'a') && do { # link attribute declaration
+ # NOT YET IMPLEMENTED!
+ next dispatch;
+ };
+
+ ($c eq 'D') && do { # data attribute declaration
+ $data =~ /^(\S+) (\S+) (\S+)( (.*))?$/
+ || croak "Bad data-attribute event data: $data";
+ my ($ename,$aname,$type,$value) = ($1,$2,$3,$5);
+ my $entity = $self->{'current_entities'}->{$ename};
+ my $attribute = new SGMLS_Attribute($aname,$type,$value);
+ $entity->set_data_attribute($attribute);
+ next dispatch;
+ };
+
+ ($c eq 'N') && do { # notation declaration
+ $self->{'current_notations'}->{$data} =
+ new SGMLS_Notation($data,
+ $self->{'current_sysid'},
+ $self->{'current_pubid'});
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ next dispatch;
+ };
+
+ ($c eq 'E') && do { # external entity declaration
+ $data =~ /^(\S+) (\S+) (\S+)$/
+ || croak "Bad external entity event data: $data";
+ my ($name,$type,$nname) = ($1,$2,$3);
+ my $notation = $self->{'current_notations'}->{$nname} if $nname;
+ $self->{'current_entities'}->{$name} =
+ new SGMLS_Entity($name,
+ $type,
+ '',
+ $self->{'current_sysid'},
+ $self->{'current_pubid'},
+ $self->{'current_filenames'},
+ $notation);
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ $self->{'current_filenames'} = [];
+ next dispatch;
+ };
+
+ ($c eq 'I') && do { # internal entity declaration
+ $data =~ /^(\S+) (\S+) (.*)$/
+ || croak "Bad external entity event data: $data";
+ my ($name,$type,$value) = ($1,$2,$3);
+ $self->{'current_entities'}->{$name} =
+ new SGMLS_Entity($name, $type, $value);
+ next dispatch;
+ };
+
+ ($c eq 'T') && do { # external text entity declaration
+ $self->{'current_entities'}->{$data} =
+ new SGMLS_Entity($data,
+ 'TEXT',
+ '',
+ $self->{'current_sysid'},
+ $self->{'current_pubid'},
+ $self->{'current_filenames'},
+ '');
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ $self->{'current_filenames'} = [];
+ next dispatch;
+ };
+
+ ($c eq 'S') && do { # subdocument entity declaration
+ $self->{'current_entities'}->{$data} =
+ new SGMLS_Entity($data,
+ 'SUBDOC',
+ '',
+ $self->{'current_sysid'},
+ $self->{'current_pubid'},
+ $self->{'current_filenames'},
+ '');
+ $self->{'current_sysid'} = '';
+ $self->{'current_pubid'} = '';
+ $self->{'current_filenames'} = [];
+ next dispatch;
+ };
+
+ ($c eq 's') && do { # system id
+ $self->{'current_sysid'} = $data;
+ next dispatch;
+ };
+
+ ($c eq 'p') && do { # public id
+ $self->{'current_pubid'} = $data;
+ next dispatch;
+ };
+
+ ($c eq 'f') && do { # generated filename
+ push @{$self->{'current_filenames'}}, $data;
+ next dispatch;
+ };
+
+ ($c eq '{') && do { # begin subdocument entity
+ my $subdoc = ($self->{'current_entities'}->{$data}||
+ croak "Unknown SUBDOC entity $data\n");
+ push @{$self->{'notation_stack'}}, $self->{'current_notations'};
+ push @{$self->{'entity_stack'}}, $self->{'current_entities'};
+ $self->{'current_notations'} = {};
+ $self->{'current_entities'} = {};
+ return new SGMLS_Event('start_subdoc',
+ $subdoc,
+ $self);
+ };
+
+ ($c eq '}') && do { # end subdocument entity
+ $self->{'current_notations'} = pop @{$self->{'notation_stack'}};
+ $self->{'current_entities'} = pop @{$self->{'entity_stack'}};
+ return new SGMLS_Event('end_subdoc',
+ ($self->{'current_entities'}->{$data} ||
+ croak "Unknown SUBDOC entity $data\n"),
+ $self);
+ };
+
+ ($c eq 'L') && do { # line number (and file name)
+ $data =~ /^(\d+)( (.*))?$/;
+ $self->{'current_line'} = $1;
+ $self->{'current_file'} = $3 if $3;
+ next dispatch;
+ };
+
+ ($c eq '#') && do { # APPINFO parameter
+ $self->{'appinfo'} = $data;
+ next dispatch;
+ };
+
+ ($c eq 'C') && do { # document is conforming
+ return new SGMLS_Event('conforming','',$self);
+ };
+ }
+ return '';
+}
+
+1;
+
+########################################################################
+# Local Variables:
+# mode: perl
+# End:
+########################################################################
diff --git a/info/examples/lwc/ch7/any.xml b/info/examples/lwc/ch7/any.xml
new file mode 100644
index 0000000000..4150c68bb7
--- /dev/null
+++ b/info/examples/lwc/ch7/any.xml
@@ -0,0 +1,18 @@
+<article>
+ <title>This is the article's title</title>
+ <author>Author One</author>
+ <author>Author Two</author>
+ <abstract>A <emph>short</emph> description of the contents</abstract>
+ <section>
+ <stitle>First section title</stitle>
+ <par>The first paragraph for this section.</par>
+ <par>A paragraph with <emph>emphasised</emph> text.</par>
+ <par>This is the end of the section.</par>
+ </section>
+ <section>
+ <stitle>Second section title</stitle>
+ <par>This is <emph>emph</emph> and <emph>more emph</emph> text.</par>
+ <par>Paragraph with <bold>bold</bold> and
+ <emph>emphasised</emph> text.</par>
+ </section>
+</article>
diff --git a/info/examples/lwc/ch7/any.xsl b/info/examples/lwc/ch7/any.xsl
new file mode 100644
index 0000000000..ecbb646198
--- /dev/null
+++ b/info/examples/lwc/ch7/any.xsl
@@ -0,0 +1,25 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
+<xsl:template match="/">
+ <xsl:text>(*root*)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/*root*)</xsl:text>
+</xsl:template>
+<xsl:template match="*" priority="-1">
+ <xsl:text>(*)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/*)</xsl:text>
+</xsl:template>
+<xsl:template match="*[position()=1 and position()=last()]" priority="1">
+ <xsl:text>($)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/$)</xsl:text>
+</xsl:template>
+</xsl:stylesheet>
+
+
+
+
+
+
+
diff --git a/info/examples/lwc/ch7/catalog b/info/examples/lwc/ch7/catalog
new file mode 100644
index 0000000000..f2393cb97a
--- /dev/null
+++ b/info/examples/lwc/ch7/catalog
@@ -0,0 +1,5 @@
+SGMLDECL "xml.dcl"
+PUBLIC "-//W3C//DTD Specification::19971229//EN" "xmlspec.dtd"
+PUBLIC "-//James Clark//DTD DSSSL Flow Object Tree//EN" "fot.dtd"
+PUBLIC "-//James Clark//DTD DSSSL Style-Sheet//EN" "style-sheet.dtd"
+PUBLIC "ISO/IEC 10179:1996//DTD DSSSL Architecture//EN" "dsssl.dtd"
diff --git a/info/examples/lwc/ch7/catalog.dsssl b/info/examples/lwc/ch7/catalog.dsssl
new file mode 100644
index 0000000000..0c48f28734
--- /dev/null
+++ b/info/examples/lwc/ch7/catalog.dsssl
@@ -0,0 +1,3 @@
+PUBLIC "-//James Clark//DTD DSSSL Flow Object Tree//EN" "fot.dtd"
+PUBLIC "-//James Clark//DTD DSSSL Style-Sheet//EN" "style-sheet.dtd"
+PUBLIC "ISO/IEC 10179:1996//DTD DSSSL Architecture//EN" "dsssl.dtd"
diff --git a/info/examples/lwc/ch7/catalog.xml b/info/examples/lwc/ch7/catalog.xml
new file mode 100644
index 0000000000..bd4f2aa939
--- /dev/null
+++ b/info/examples/lwc/ch7/catalog.xml
@@ -0,0 +1,2 @@
+SGMLDECL "xml.dcl"
+PUBLIC "-//W3C//DTD Specification::19971229//EN" "xmlspec.dtd"
diff --git a/info/examples/lwc/ch7/debug.txt b/info/examples/lwc/ch7/debug.txt
new file mode 100644
index 0000000000..f4c0cf8910
--- /dev/null
+++ b/info/examples/lwc/ch7/debug.txt
@@ -0,0 +1,789 @@
+START OF ELEMENT fo:page-sequence
+start of fo:page-sequence [
+setfont
+new hbox: /F5 12 Tf
+
+move 42 -800
+new hbox: 42 800 Td
+
+shipping current hbox list
+HBoxList
+--------
+ /F5 12 Tf
+ 42 800 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ /F5 12 Tf
+ 42 800 Td
+ -0 0 Td
+%]
+--------
+
+] start of fo:page-sequence
+CHARACTERS
+START OF ELEMENT fo:block
+start of fo:block [
+setfont
+new hbox: /F3 24 Tf
+
+MOVE because indent-start=0 total_indent=42 margin-left=42 space-before=0 linespacing=12:
+move 0 12
+new hbox: 0 -12 Td
+
+] start of fo:block
+CHARACTERS
+END OF ELEMENT fo:block
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ ( ) Tj
+ /F3 24 Tf
+ 0 -12 Td
+ (INVITATION) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=59][
+ 59 0 Td
+ /F3 24 Tf
+ 0 -12 Td
+ (INVITATION) Tj
+ 0 0 Td
+ -59 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+new hbox: /F5 12 Tf
+
+START OF ELEMENT fo:list
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=42 margin-left=42 space-before=0 linespacing=12:
+move 0 12
+new hbox: 0 -12 Td
+
+] start of fo:block
+START OF ELEMENT fo:list-item
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=42 margin-left=42 space-before=0 linespacing=12:
+move 0 12
+new hbox: 0 -12 Td
+
+] start of fo:block
+START OF ELEMENT fo:list-item-label
+setfont
+new hbox: /F6 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:list-item-label
+move 56 0
+new hbox: 56 0 Td
+
+setfont
+new hbox: /F5 12 Tf
+
+START OF ELEMENT fo:list-item-body
+setfont
+CHARACTERS
+END OF ELEMENT fo:list-item-body
+setfont
+END OF ELEMENT fo:list-item
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ /F5 12 Tf
+ 0 -12 Td
+ 0 -12 Td
+ /F6 12 Tf
+ (To:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (Anna,) Tj
+ ( ) Tj
+ (Bernard,) Tj
+ ( ) Tj
+ (Didier,) Tj
+ ( ) Tj
+ (Johanna) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ /F5 12 Tf
+ 0 -12 Td
+ 0 -12 Td
+ /F6 12 Tf
+ (To:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (Anna,) Tj
+ ( ) Tj
+ (Bernard,) Tj
+ ( ) Tj
+ (Didier,) Tj
+ ( ) Tj
+ (Johanna) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+START OF ELEMENT fo:list-item
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=98 margin-left=42 space-before=0 linespacing=12:
+move -56 12
+new hbox: -56 -12 Td
+
+] start of fo:block
+START OF ELEMENT fo:list-item-label
+setfont
+new hbox: /F6 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:list-item-label
+move 56 0
+new hbox: 56 0 Td
+
+setfont
+new hbox: /F5 12 Tf
+
+START OF ELEMENT fo:list-item-body
+setfont
+CHARACTERS
+END OF ELEMENT fo:list-item-body
+setfont
+END OF ELEMENT fo:list-item
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ -56 -12 Td
+ /F6 12 Tf
+ (When:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (Next) Tj
+ ( ) Tj
+ (Friday) Tj
+ ( ) Tj
+ (Evening) Tj
+ ( ) Tj
+ (at) Tj
+ ( ) Tj
+ (8) Tj
+ ( ) Tj
+ (pm) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ /F6 12 Tf
+ (When:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (Next) Tj
+ ( ) Tj
+ (Friday) Tj
+ ( ) Tj
+ (Evening) Tj
+ ( ) Tj
+ (at) Tj
+ ( ) Tj
+ (8) Tj
+ ( ) Tj
+ (pm) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+START OF ELEMENT fo:list-item
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=98 margin-left=42 space-before=0 linespacing=12:
+move -56 12
+new hbox: -56 -12 Td
+
+] start of fo:block
+START OF ELEMENT fo:list-item-label
+setfont
+new hbox: /F6 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:list-item-label
+move 56 0
+new hbox: 56 0 Td
+
+setfont
+new hbox: /F5 12 Tf
+
+START OF ELEMENT fo:list-item-body
+setfont
+CHARACTERS
+END OF ELEMENT fo:list-item-body
+setfont
+END OF ELEMENT fo:list-item
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ -56 -12 Td
+ /F6 12 Tf
+ (Venue:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (The) Tj
+ ( ) Tj
+ (Web) Tj
+ ( ) Tj
+ (Cafe) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ /F6 12 Tf
+ (Venue:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (The) Tj
+ ( ) Tj
+ (Web) Tj
+ ( ) Tj
+ (Cafe) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+START OF ELEMENT fo:list-item
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=98 margin-left=42 space-before=0 linespacing=12:
+move -56 12
+new hbox: -56 -12 Td
+
+] start of fo:block
+START OF ELEMENT fo:list-item-label
+setfont
+new hbox: /F6 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:list-item-label
+move 56 0
+new hbox: 56 0 Td
+
+setfont
+new hbox: /F5 12 Tf
+
+START OF ELEMENT fo:list-item-body
+setfont
+CHARACTERS
+END OF ELEMENT fo:list-item-body
+setfont
+END OF ELEMENT fo:list-item
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ -56 -12 Td
+ /F6 12 Tf
+ (Occasion:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (My) Tj
+ ( ) Tj
+ (first) Tj
+ ( ) Tj
+ (XML) Tj
+ ( ) Tj
+ (baby) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ /F6 12 Tf
+ (Occasion:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (My) Tj
+ ( ) Tj
+ (first) Tj
+ ( ) Tj
+ (XML) Tj
+ ( ) Tj
+ (baby) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+END OF ELEMENT fo:list
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+CHARACTERS
+START OF ELEMENT fo:block
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=98 margin-left=42 space-before=0 linespacing=12:
+move -56 12
+new hbox: -56 -12 Td
+
+] start of fo:block
+CHARACTERS
+START OF ELEMENT fo:sequence
+setfont
+new hbox: /F6 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:sequence
+setfont
+new hbox: /F5 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:block
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ ( ) Tj
+ -56 -12 Td
+ ( ) Tj
+ (I) Tj
+ ( ) Tj
+ (would) Tj
+ ( ) Tj
+ (like) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (invite) Tj
+ ( ) Tj
+ (you) Tj
+ ( ) Tj
+ (all) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (celebrate) Tj
+ ( ) Tj
+ (the) Tj
+ ( ) Tj
+ (birth) Tj
+ ( ) Tj
+ (of) Tj
+ ( ) Tj
+ /F6 12 Tf
+ (Invitation) Tj
+ /F5 12 Tf
+ (,) Tj
+ ( ) Tj
+ (my) Tj
+ ( ) Tj
+ (first) Tj
+ ( ) Tj
+ (XML) Tj
+ ( ) Tj
+ (document) Tj
+ ( ) Tj
+ (child.) Tj
+ ( ) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ (I) Tj
+ ( ) Tj
+ (would) Tj
+ ( ) Tj
+ (like) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (invite) Tj
+ ( ) Tj
+ (you) Tj
+ ( ) Tj
+ (all) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (celebrate) Tj
+ ( ) Tj
+ (the) Tj
+ ( ) Tj
+ (birth) Tj
+ ( ) Tj
+ (of) Tj
+ ( ) Tj
+ /F6 12 Tf
+ -0 0 Td
+%]
+% vbox-movedown[linespacing=12][
+ 0 -12 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ (Invitation) Tj
+ /F5 12 Tf
+ (,) Tj
+ ( ) Tj
+ (my) Tj
+ ( ) Tj
+ (first) Tj
+ ( ) Tj
+ (XML) Tj
+ ( ) Tj
+ (document) Tj
+ ( ) Tj
+ (child.) Tj
+ ( ) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+CHARACTERS
+START OF ELEMENT fo:block
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=42 margin-left=42 space-before=0 linespacing=12:
+move 0 12
+new hbox: 0 -12 Td
+
+] start of fo:block
+CHARACTERS
+END OF ELEMENT fo:block
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ ( ) Tj
+ 0 -12 Td
+ ( ) Tj
+ (Please) Tj
+ ( ) Tj
+ (do) Tj
+ ( ) Tj
+ (your) Tj
+ ( ) Tj
+ (best) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (come) Tj
+ ( ) Tj
+ (and) Tj
+ ( ) Tj
+ (join) Tj
+ ( ) Tj
+ (me) Tj
+ ( ) Tj
+ (next) Tj
+ ( ) Tj
+ (Friday) Tj
+ ( ) Tj
+ (evening.) Tj
+ ( ) Tj
+ (And,) Tj
+ ( ) Tj
+ (do) Tj
+ ( ) Tj
+ (not) Tj
+ ( ) Tj
+ (forget) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (bring) Tj
+ ( ) Tj
+ (your) Tj
+ ( ) Tj
+ (friends.) Tj
+ ( ) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ 0 -12 Td
+ (Please) Tj
+ ( ) Tj
+ (do) Tj
+ ( ) Tj
+ (your) Tj
+ ( ) Tj
+ (best) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (come) Tj
+ ( ) Tj
+ (and) Tj
+ ( ) Tj
+ (join) Tj
+ ( ) Tj
+ (me) Tj
+ ( ) Tj
+ (next) Tj
+ ( ) Tj
+ (Friday) Tj
+ ( ) Tj
+ -0 0 Td
+%]
+% vbox-movedown[linespacing=12][
+ 0 -12 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ (evening.) Tj
+ ( ) Tj
+ (And,) Tj
+ ( ) Tj
+ (do) Tj
+ ( ) Tj
+ (not) Tj
+ ( ) Tj
+ (forget) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (bring) Tj
+ ( ) Tj
+ (your) Tj
+ ( ) Tj
+ (friends.) Tj
+ ( ) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+CHARACTERS
+START OF ELEMENT fo:block
+start of fo:block [
+setfont
+MOVE because indent-start=0 total_indent=42 margin-left=42 space-before=0 linespacing=12:
+move 0 12
+new hbox: 0 -12 Td
+
+] start of fo:block
+CHARACTERS
+START OF ELEMENT fo:sequence
+setfont
+new hbox: /F6 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:sequence
+setfont
+new hbox: /F5 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:block
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ ( ) Tj
+ 0 -12 Td
+ ( ) Tj
+ (I) Tj
+ ( ) Tj
+ /F6 12 Tf
+ (really) Tj
+ /F5 12 Tf
+ ( ) Tj
+ (look) Tj
+ ( ) Tj
+ (forward) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (see) Tj
+ ( ) Tj
+ (you) Tj
+ ( ) Tj
+ (soon!) Tj
+ ( ) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ 0 -12 Td
+ (I) Tj
+ ( ) Tj
+ /F6 12 Tf
+ (really) Tj
+ /F5 12 Tf
+ ( ) Tj
+ (look) Tj
+ ( ) Tj
+ (forward) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (see) Tj
+ ( ) Tj
+ (you) Tj
+ ( ) Tj
+ (soon!) Tj
+ ( ) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+CHARACTERS
+START OF ELEMENT fo:block
+start of fo:block [
+setfont
+new hbox: /F7 12 Tf
+
+MOVE because indent-start=0 total_indent=42 margin-left=42 space-before=0 linespacing=12:
+move 0 12
+new hbox: 0 -12 Td
+
+] start of fo:block
+CHARACTERS
+END OF ELEMENT fo:block
+end of fo:block [
+MOVE because indent-start=0 space-after=0:
+move 0 0
+new hbox: 0 0 Td
+
+shipping current hbox list
+HBoxList
+--------
+ ( ) Tj
+ /F7 12 Tf
+ 0 -12 Td
+ (From:) Tj
+ ( ) Tj
+ (Michel) Tj
+ 0 0 Td
+--------
+
+VBoxList
+--------
+% vbox-box[extra-start-indent=185][
+ 185 0 Td
+ /F7 12 Tf
+ 0 -12 Td
+ (From:) Tj
+ ( ) Tj
+ (Michel) Tj
+ 0 0 Td
+ -185 0 Td
+%]
+--------
+
+] end of fo:block
+setfont
+new hbox: /F5 12 Tf
+
+CHARACTERS
+END OF ELEMENT fo:page-sequence
+setfont
+new hbox: /F5 10 Tf
+
diff --git a/info/examples/lwc/ch7/dsssl.cat b/info/examples/lwc/ch7/dsssl.cat
new file mode 100644
index 0000000000..76a78096b1
--- /dev/null
+++ b/info/examples/lwc/ch7/dsssl.cat
@@ -0,0 +1,3 @@
+PUBLIC "-//James Clark//DTD DSSSL Flow Object Tree//EN" "fot.dtd"
+PUBLIC "ISO/IEC 10179:1996//DTD DSSSL Architecture//EN" "dsssl.dtd"
+PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" "style-sheet.dtd"
diff --git a/info/examples/lwc/ch7/dsssl.dtd b/info/examples/lwc/ch7/dsssl.dtd
new file mode 100644
index 0000000000..50f66baa67
--- /dev/null
+++ b/info/examples/lwc/ch7/dsssl.dtd
@@ -0,0 +1,134 @@
+<!-- DSSSL Architectural Forms -->
+
+<!ENTITY % declarations
+ "features | baseset-encoding | literal-described-char | add-name-chars
+ | add-separator-chars | standard-chars | other-chars
+ | combine-char | map-sdata-entity | char-repertoire"
+>
+
+<!element dsssl-specification - O
+ ((%declarations;)*,
+ (style-specification | transformation-specification
+ | external-specification)+)>
+<!attlist dsssl-specification
+ version CDATA #FIXED "ISO/IEC 10179:1996"
+>
+
+<!element transformation-specification - O
+ ((%declarations;)*, transformation-specification-body*)>
+<!attlist transformation-specification
+ id ID #IMPLIED
+ desc CDATA #IMPLIED
+ -- human readable description of specification --
+ partial (partial | complete) complete
+ -- is the specification complete is or is it just a fragment
+ to be used in other specifications? --
+ use -- reftype(transformation-specification|external-specification) --
+ IDREFS #IMPLIED -- Default: none --
+ entities
+ -- entities available to be specified as DTD for validation
+ of result document --
+ ENTITIES #IMPLIED -- Default: none --
+>
+
+<!element style-specification - O
+ ((%declarations;)*, style-specification-body*)>
+<!attlist style-specification
+ id ID #IMPLIED
+ desc CDATA #IMPLIED
+ -- human readable description of specification --
+ partial (partial | complete) complete
+ -- is the specification complete is or is it just a fragment
+ to be used in other specifications? --
+ use -- reftype(style-specification|external-specification) --
+ IDREFS #IMPLIED -- Default: none --
+>
+
+<!-- Assign a local ID to a specification in another document. -->
+<!element external-specification - O EMPTY>
+<!attlist external-specification
+ id ID #REQUIRED
+ document -- document containing spec --
+ ENTITY #REQUIRED
+ specid -- id of spec in document --
+ NAME #IMPLIED -- Default: first spec in document --
+>
+
+<!-- Declares features used by specification. -->
+<!element features - O (#PCDATA)
+ -- dlextype(featurename*) -->
+
+<!-- Map character numbers in a base character set to character names;
+not needed when system knows a character set, and all characters
+in character set have universal code. -->
+<!element baseset-encoding - O (#PCDATA)
+ -- dlextype((number, charname)*) -->
+<!attlist baseset-encoding
+ name CDATA #REQUIRED -- public identifier of baseset --
+>
+
+<!-- Map a character described in the SGML declaration with a minimum literal
+to a character name. -->
+<!element literal-described-char - O (#PCDATA)
+ -- dlextype(charname) -->
+<!attlist literal-described-char
+ desc CDATA #REQUIRED -- the literal description --
+>
+
+<!-- Declare additional characters allowed in name within DSSSL notation. -->
+<!element add-name-chars - O (#PCDATA)
+ -- dlextype(charname*) -->
+
+<!-- Declare additional characters allowed as separators within
+DSSSL notation. -->
+<!element add-separator-chars - O (#PCDATA)
+ -- dlextype(charname*) -->
+
+<!-- Define characters associating names with universal codes. -->
+
+<!element standard-chars - O (#PCDATA)
+ -- dlextype((charname, number))*) -->
+
+<!-- Define characters with no universal codes. -->
+
+<!element other-chars - O (#PCDATA)
+ -- dlextype(charname*) -->
+
+<!-- Map an SDATA entity onto a character. -->
+
+<!element map-sdata-entity - O (#PCDATA)
+ -- dlextype(charname) -->
+<!attlist map-sdata-entity
+ name CDATA #IMPLIED -- Default: mapping uses replacement text only --
+ text CDATA #IMPLIED -- Default: mapping uses name only --
+>
+
+<!-- Declare character combining. -->
+
+<!element combine-char - O (#PCDATA)
+ -- dlextype(charname, charname, charname+) -->
+
+<!-- Declare a character repertoire. -->
+<!element char-repertoire - O EMPTY>
+<!attlist char-repertoire
+ name -- public identifier for repertoire --
+ CDATA #REQUIRED
+>
+
+<!element style-specification-body - - CDATA
+ -- content uses notation of DSSSL style language -->
+<!attlist style-specification-body
+ content ENTITY #CONREF -- Default: syntactic content --
+>
+
+<!element transformation-specification-body - - CDATA
+ -- content uses notation of DSSSL transformation language -->
+<!attlist transformation-specification-body
+ content ENTITY #CONREF -- Default: syntactic content --
+>
+
+<!-- This notation is intended for use as the value of the ArcDataF
+ architectural form support attribute. -->
+
+<!NOTATION dsssl-specification PUBLIC
+ "ISO/IEC 10179:1996//NOTATION DSSSL Specification//EN">
diff --git a/info/examples/lwc/ch7/empty.dsl b/info/examples/lwc/ch7/empty.dsl
new file mode 100644
index 0000000000..49af0a6b5c
--- /dev/null
+++ b/info/examples/lwc/ch7/empty.dsl
@@ -0,0 +1,8 @@
+<!-- empty.dsl -->
+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style-Sheet//EN">
+<style-sheet>
+ <style-specification>
+ <style-specification-body>
+ </style-specification-body>
+ </style-specification>
+</style-sheet>
diff --git a/info/examples/lwc/ch7/empty.xsl b/info/examples/lwc/ch7/empty.xsl
new file mode 100644
index 0000000000..17be6717a8
--- /dev/null
+++ b/info/examples/lwc/ch7/empty.xsl
@@ -0,0 +1,2 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
+</xsl:stylesheet>
diff --git a/info/examples/lwc/ch7/emptyexample.xml b/info/examples/lwc/ch7/emptyexample.xml
new file mode 100644
index 0000000000..957a604106
--- /dev/null
+++ b/info/examples/lwc/ch7/emptyexample.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE emptyexample [
+<!ELEMENT emptyexample (par*)>
+<!ELEMENT par (#PCDATA|image|imref)*>
+<!ELEMENT image EMPTY>
+<!ATTLIST image name ID #IMPLIED
+ address CDATA #REQUIRED>
+<!ELEMENT imref EMPTY>
+<!ATTLIST imref name IDREF #REQUIRED>
+<!ENTITY logo-uri "http://www.ucc.ie/xml/xml.gif">
+]>
+<emptyexample>
+<par>The XML logo is shown in the image <imref name="xml-logo"/>.</par>
+<par>The image shows an alternative syntax for an empty element
+<image name="xml-logo" address="&logo-uri;"></image></par>
+</emptyexample>
diff --git a/info/examples/lwc/ch7/fot.dtd b/info/examples/lwc/ch7/fot.dtd
new file mode 100644
index 0000000000..afe3576dc5
--- /dev/null
+++ b/info/examples/lwc/ch7/fot.dtd
@@ -0,0 +1,507 @@
+<!-- Typical use:
+
+<!DOCTYPE fot PUBLIC "-//James Clark//DTD DSSSL Flow Object Tree//EN" "fot.dtd">
+
+-->
+<!ENTITY % length-spec "CDATA">
+<!-- represents length-spec or #f; #f is represented by empty value -->
+<!ENTITY % opt-length-spec "CDATA">
+<!ENTITY % length "NMTOKEN">
+<!ENTITY % enum "NMTOKEN">
+<!ENTITY % enum-or-boolean "NMTOKEN">
+<!ENTITY % boolean "(true|false)">
+
+<!ENTITY % flow "
+(paragraph
+|sequence
+|display-group
+|line-field
+|link
+|scroll
+|marginalia
+|leader
+|sideline
+|box
+|score
+|table-row
+|math-sequence
+|unmath
+|subscript
+|superscript
+|grid
+|grid-cell
+|paragraph-break
+|external-graphic
+|rule
+|alignment-point
+|table-column
+|character
+|simple-page-sequence
+|fraction
+|script
+|mark
+|fence
+|radical
+|math-operator
+|table
+|table-part
+|table-cell
+|multi-mode
+|page-number
+|text
+|sdata
+|a
+|define-glyph-subst-table)*">
+
+<!ELEMENT fot %flow;>
+<!ELEMENT text (#PCDATA)>
+<!ELEMENT sdata EMPTY>
+<!ATTLIST sdata name CDATA #REQUIRED text CDATA #REQUIRED>
+
+<!ELEMENT paragraph %flow;>
+<!ELEMENT sequence %flow;>
+<!ELEMENT display-group %flow;>
+<!ELEMENT line-field %flow;>
+<!ELEMENT link %flow;>
+<!ELEMENT scroll %flow;>
+<!ELEMENT marginalia %flow;>
+<!ELEMENT leader %flow;>
+<!ELEMENT sideline %flow;>
+<!ELEMENT box %flow;>
+<!ELEMENT score %flow;>
+<!ELEMENT table-row %flow;>
+<!ELEMENT math-sequence %flow;>
+<!ELEMENT unmath %flow;>
+<!ELEMENT subscript %flow;>
+<!ELEMENT superscript %flow;>
+<!ELEMENT grid %flow;>
+<!ELEMENT grid-cell %flow;>
+<!ELEMENT paragraph-break EMPTY>
+<!ELEMENT external-graphic EMPTY>
+<!ELEMENT rule EMPTY>
+<!ELEMENT alignment-point EMPTY>
+<!ELEMENT table-column EMPTY>
+<!ELEMENT character EMPTY>
+
+<!ELEMENT page-number EMPTY>
+<!ATTLIST page-number ref CDATA #IMPLIED>
+
+<!ELEMENT define-glyph-subst-table (glyph-subst*)>
+<!ATTLIST define-glyph-subst-table id ID #REQUIRED>
+
+<!ELEMENT glyph-subst EMPTY>
+<!ATTLIST glyph-subst old CDATA #REQUIRED new CDATA #REQUIRED>
+
+<!ELEMENT a EMPTY>
+<!ATTLIST a
+ name CDATA #REQUIRED
+>
+
+<!ELEMENT simple-page-sequence
+ ((simple-page-sequence.right-header
+ |simple-page-sequence.center-header
+ |simple-page-sequence.left-header
+ |simple-page-sequence.right-footer
+ |simple-page-sequence.center-footer
+ |simple-page-sequence.left-footer)*,
+ %flow;)
+>
+
+<!ELEMENT simple-page-sequence.left-header %flow;>
+<!ELEMENT simple-page-sequence.right-header %flow;>
+<!ELEMENT simple-page-sequence.center-header %flow;>
+<!ELEMENT simple-page-sequence.left-footer %flow;>
+<!ELEMENT simple-page-sequence.right-footer %flow;>
+<!ELEMENT simple-page-sequence.center-footer %flow;>
+
+<!ENTITY % hf "
+ front %boolean; #IMPLIED
+ first %boolean; #IMPLIED
+">
+
+<!ATTLIST simple-page-sequence.right-header %hf;>
+<!ATTLIST simple-page-sequence.center-header %hf;>
+<!ATTLIST simple-page-sequence.left-footer %hf;>
+<!ATTLIST simple-page-sequence.right-footer %hf;>
+<!ATTLIST simple-page-sequence.center-footer %hf;>
+
+<!ELEMENT table
+(table.before-row-border, table.after-row-border,
+ table.before-column-border, table.after-column-border,
+ %flow;)>
+
+<!ELEMENT table.before-row-border EMPTY>
+<!ELEMENT table.after-row-border EMPTY>
+<!ELEMENT table.before-column-border EMPTY>
+<!ELEMENT table.after-column-border EMPTY>
+
+<!ELEMENT table-part
+ (table-part.principal, table-part.header, table-part.footer)
+>
+
+<!ELEMENT table-part.header %flow;>
+<!ELEMENT table-part.footer %flow;>
+<!ELEMENT table-part.principal %flow;>
+
+<!ELEMENT table-cell
+(table-cell.before-row-border, table-cell.after-row-border,
+ table-cell.before-column-border, table-cell.after-column-border,
+ %flow;)>
+
+<!ELEMENT table-cell.before-row-border EMPTY>
+<!ELEMENT table-cell.after-row-border EMPTY>
+<!ELEMENT table-cell.before-column-border EMPTY>
+<!ELEMENT table-cell.after-column-border EMPTY>
+
+<!ELEMENT fraction
+ (fraction.fraction-bar, fraction.numerator, fraction.denominator)>
+<!ELEMENT fraction.numerator %flow;>
+<!ELEMENT fraction.denominator %flow;>
+<!ELEMENT fraction.fraction-bar EMPTY>
+
+<!ELEMENT script (script.principal,
+ script.pre-sup, script.pre-sub,
+ script.post-sup, script.post-sub,
+ script.mid-sup, script.mid-sub)>
+
+<!ELEMENT script.principal %flow;>
+<!ELEMENT script.pre-sup %flow;>
+<!ELEMENT script.pre-sub %flow;>
+<!ELEMENT script.post-sup %flow;>
+<!ELEMENT script.post-sub %flow;>
+<!ELEMENT script.mid-sup %flow;>
+<!ELEMENT script.mid-sub %flow;>
+
+<!ELEMENT mark (mark.principal, mark.over-mark, mark.under-mark)>
+<!ELEMENT mark.principal %flow;>
+<!ELEMENT mark.over-mark %flow;>
+<!ELEMENT mark.under-mark %flow;>
+
+<!ELEMENT fence (fence.principal, fence.open, fence.close)>
+<!ELEMENT fence.principal %flow;>
+<!ELEMENT fence.open %flow;>
+<!ELEMENT fence.close %flow;>
+
+<!ELEMENT radical (radical.radical?, radical.principal, radical.degree)>
+<!ELEMENT radical.principal %flow;>
+<!ELEMENT radical.degree %flow;>
+<!ELEMENT radical.radical EMPTY>
+
+<!ELEMENT math-operator (math-operator.principal, math-operator.operator,
+ math-operator.lower-limit, math-operator.upper-limit)>
+<!ELEMENT math-operator.principal %flow;>
+<!ELEMENT math-operator.operator %flow;>
+<!ELEMENT math-operator.lower-limit %flow;>
+<!ELEMENT math-operator.upper-limit %flow;>
+
+<!ELEMENT multi-mode (multi-mode.mode, multi-mode.mode+)>
+<!ELEMENT multi-mode.mode %flow;>
+<!ATTLIST multi-mode.mode
+ name CDATA #IMPLIED
+ desc CDATA #IMPLIED
+>
+
+<!ENTITY % inherited-characteristics "
+font-size %length; #IMPLIED
+font-family-name CDATA #IMPLIED
+font-weight %enum-or-boolean; #IMPLIED
+font-posture %enum-or-boolean; #IMPLIED
+start-indent %length-spec; #IMPLIED
+end-indent %length-spec; #IMPLIED
+first-line-start-indent %length-spec; #IMPLIED
+last-line-end-indent %length-spec; #IMPLIED
+line-spacing %length-spec; #IMPLIED
+min-pre-line-spacing %opt-length-spec; #IMPLIED
+min-post-line-spacing %opt-length-spec; #IMPLIED
+min-leading %opt-length-spec; #IMPLIED
+field-width %length-spec; #IMPLIED
+lines %enum; #IMPLIED
+quadding %enum; #IMPLIED
+display-alignment %enum; #IMPLIED
+field-align %enum; #IMPLIED
+marginalia-side %enum; #IMPLIED
+principal-mode-simultaneous %boolean; #IMPLIED
+marginalia-sep %length-spec; #IMPLIED
+marginalia-keep-with-previous %boolean; #IMPLIED
+grid-equidistant-rows %boolean; #IMPLIED
+grid-equidistant-columns %boolean; #IMPLIED
+color CDATA #IMPLIED
+background-color CDATA #IMPLIED
+page-width %length; #IMPLIED
+page-height %length; #IMPLIED
+left-margin %length; #IMPLIED
+right-margin %length; #IMPLIED
+top-margin %length; #IMPLIED
+bottom-margin %length; #IMPLIED
+header-margin %length; #IMPLIED
+footer-margin %length; #IMPLIED
+border-present %boolean; #IMPLIED
+hyphenate %boolean; #IMPLIED
+kern %boolean; #IMPLIED
+ligature %boolean; #IMPLIED
+score-spaces %boolean; #IMPLIED
+float-out-marginalia %boolean; #IMPLIED
+float-out-sidelines %boolean; #IMPLIED
+float-out-line-numbers %boolean; #IMPLIED
+cell-background %boolean; #IMPLIED
+span-weak %boolean; #IMPLIED
+ignore-record-end %boolean; #IMPLIED
+numbered-lines %boolean; #IMPLIED
+hanging-punct %boolean; #IMPLIED
+box-open-end %boolean; #IMPLIED
+truncate-leader %boolean; #IMPLIED
+align-leader %boolean; #IMPLIED
+table-part-omit-middle-header %boolean; #IMPLIED
+table-part-omit-middle-footer %boolean; #IMPLIED
+border-omit-at-break %boolean; #IMPLIED
+line-join %enum; #IMPLIED
+line-cap %enum; #IMPLIED
+line-number-side %enum; #IMPLIED
+kern-mode %enum; #IMPLIED
+input-whitespace-treatment %enum; #IMPLIED
+filling-direction %enum; #IMPLIED
+writing-mode %enum; #IMPLIED
+last-line-quadding %enum; #IMPLIED
+math-display-mode %enum; #IMPLIED
+script-pre-align %enum; #IMPLIED
+script-post-align %enum; #IMPLIED
+script-mid-sup-align %enum; #IMPLIED
+script-mid-sub-align %enum; #IMPLIED
+numerator-align %enum; #IMPLIED
+denominator-align %enum; #IMPLIED
+grid-position-cell-type %enum; #IMPLIED
+grid-column-alignment %enum; #IMPLIED
+grid-row-Alignment %enum; #IMPLIED
+box-type %enum; #IMPLIED
+glyph-alignment-mode %enum; #IMPLIED
+box-border-alignment %enum; #IMPLIED
+cell-row-alignment %enum; #IMPLIED
+border-alignment %enum; #IMPLIED
+sideline-side %enum; #IMPLIED
+hyphenation-keep %enum-or-boolean; #IMPLIED
+font-structure %enum-or-boolean; #IMPLIED
+font-proportionate-width %enum-or-boolean; #IMPLIED
+cell-crossed %enum-or-boolean; #IMPLIED
+position-point-shift %length-spec; #IMPLIED
+start-margin %length-spec; #IMPLIED
+end-margin %length-spec; #IMPLIED
+sideline-sep %length-spec; #IMPLIED
+asis-wrap-indent %length-spec; #IMPLIED
+line-number-sep %length-spec; #IMPLIED
+last-line-justify-limit %length-spec; #IMPLIED
+justify-glyph-space-max-add %length-spec; #IMPLIED
+justify-glyph-space-max-remove %length-spec; #IMPLIED
+table-corner-radius %length-spec; #IMPLIED
+box-corner-radius %length-spec; #IMPLIED
+line-thickness %length; #IMPLIED
+cell-before-row-margin %length; #IMPLIED
+cell-after-row-margin %length; #IMPLIED
+cell-before-column-margin %length; #IMPLIED
+cell-after-column-margin %length; #IMPLIED
+line-sep %length; #IMPLIED
+box-size-before %length; #IMPLIED
+box-size-after %length; #IMPLIED
+country NMTOKEN #IMPLIED
+language NMTOKEN #IMPLIED
+expand-tabs NMTOKEN #IMPLIED
+hyphenation-ladder-count NMTOKEN #IMPLIED
+layer NMTOKEN #IMPLIED
+background-layer NMTOKEN #IMPLIED
+border-priority NMTOKEN #IMPLIED
+line-repeat NMTOKEN #IMPLIED
+span NMTOKEN #IMPLIED
+min-leader-repeat NMTOKEN #IMPLIED
+hyphenation-remain-char-count NMTOKEN #IMPLIED
+hyphenation-push-char-count NMTOKEN #IMPLIED
+widow-count NMTOKEN #IMPLIED
+orphan-count NMTOKEN #IMPLIED
+background-tile CDATA #IMPLIED
+line-breaking-method CDATA #IMPLIED
+line-composition-method CDATA #IMPLIED
+implicit-bidi-method CDATA #IMPLIED
+glyph-subst-method CDATA #IMPLIED
+glyph-reorder-method CDATA #IMPLIED
+hyphenation-method CDATA #IMPLIED
+table-auto-width-method CDATA #IMPLIED
+font-name CDATA #IMPLIED
+escapement-space-before CDATA #IMPLIED
+escapement-space-after CDATA #IMPLIED
+glyph-subst-table NMTOKENS #IMPLIED
+">
+
+<!ENTITY % display-nic "
+ position-preference %enum-or-boolean; #IMPLIED
+ keep-with-next %boolean; 'false'
+ keep-with-previous %boolean; 'false'
+ may-violate-keep-before %boolean; 'false'
+ may-violate-keep-after %boolean; 'false'
+ keep %enum-or-boolean; #IMPLIED
+ break-before %enum-or-boolean; #IMPLIED
+ break-after %enum-or-boolean; #IMPLIED
+ space-before CDATA #IMPLIED
+ space-before-conditional %boolean; #IMPLIED
+ space-before-priority NMTOKEN #IMPLIED
+ space-after CDATA #IMPLIED
+ space-after-conditional %boolean; #IMPLIED
+ space-after-priority NMTOKEN #IMPLIED
+">
+
+<!ENTITY % inline-nic "
+ break-before-priority NMTOKEN #IMPLIED
+ break-after-priority NMTOKEN #IMPLIED
+">
+
+<!ATTLIST sequence %inherited-characteristics;>
+<!ATTLIST line-field %inherited-characteristics;>
+<!ATTLIST simple-page-sequence %inherited-characteristics;>
+<!ATTLIST fraction %inherited-characteristics;>
+<!ATTLIST fraction.fraction-bar %inherited-characteristics;>
+<!ATTLIST math-sequence %inherited-characteristics;>
+<!ATTLIST unmath %inherited-characteristics;>
+<!ATTLIST subscript %inherited-characteristics;>
+<!ATTLIST superscript %inherited-characteristics;>
+<!ATTLIST script %inherited-characteristics;>
+<!ATTLIST mark %inherited-characteristics;>
+<!ATTLIST fence %inherited-characteristics;>
+<!ATTLIST radical %inherited-characteristics;>
+<!ATTLIST math-operator %inherited-characteristics;>
+<!ATTLIST sideline %inherited-characteristics;>
+<!ATTLIST scroll %inherited-characteristics;>
+<!ATTLIST marginalia %inherited-characteristics;>
+<!ATTLIST multi-mode %inherited-characteristics;>
+<!ATTLIST table-row %inherited-characteristics;>
+<!ATTLIST table.before-row-border %inherited-characteristics;>
+<!ATTLIST table.after-row-border %inherited-characteristics;>
+<!ATTLIST table.before-column-border %inherited-characteristics;>
+<!ATTLIST table.after-column-border %inherited-characteristics;>
+<!ATTLIST table-cell.before-row-border %inherited-characteristics;>
+<!ATTLIST table-cell.after-row-border %inherited-characteristics;>
+<!ATTLIST table-cell.before-column-border %inherited-characteristics;>
+<!ATTLIST table-cell.after-column-border %inherited-characteristics;>
+
+<!ATTLIST table-column
+ column-number NMTOKEN #REQUIRED
+ n-columns-spanned NMTOKEN #IMPLIED
+ width %length-spec; #IMPLIED
+ %inherited-characteristics;
+>
+
+<!ATTLIST table
+ width %length-spec; #IMPLIED
+ minimum-width %boolean; "false"
+ %display-nic;
+ %inherited-characteristics;
+>
+
+<!-- column-number of 0 has a special meaning: it identifies a dummy cell that
+ can be used to fill out the row if it later proves necessary to do so -->
+<!ATTLIST table-cell
+ column-number NMTOKEN #REQUIRED
+ n-columns-spanned NMTOKEN #IMPLIED
+ n-rows-spanned NMTOKEN #IMPLIED
+ %inherited-characteristics;
+>
+
+<!ATTLIST link
+ destination CDATA #IMPLIED
+ %inherited-characteristics;
+>
+
+<!ATTLIST box
+ display %boolean; "false"
+ %display-nic;
+ %inline-nic;
+ %inherited-characteristics;
+>
+
+<!ATTLIST score
+ type (before|through|after|char) #IMPLIED
+ type.length-spec %length-spec; #IMPLIED
+ char CDATA #IMPLIED
+ %inherited-characteristics;
+>
+
+<!ATTLIST leader
+ length %length-spec; #IMPLIED
+ %inherited-characteristics;
+ %inline-nic;
+>
+
+<!ATTLIST rule
+ orientation (horizontal|vertical|escapement|line-progression)
+ #REQUIRED
+ length %length-spec; #IMPLIED
+ %display-nic;
+ %inline-nic;
+ %inherited-characteristics;
+>
+
+<!ATTLIST external-graphic
+ display %boolean; "false"
+ scale %enum; #IMPLIED
+ scale-x NMTOKEN #IMPLIED
+ scale-y NMTOKEN #IMPLIED
+ max-width %length-spec; #IMPLIED
+ max-height %length-spec; #IMPLIED
+ entity-system-id CDATA #REQUIRED
+ notation-system-id CDATA #REQUIRED
+ escapement-direction %enum; #IMPLIED
+ position-point-x %length-spec; #IMPLIED
+ position-point-y %length-spec; #IMPLIED
+ %inline-nic;
+ %display-nic;
+ %inherited-characteristics;
+>
+
+<!ATTLIST display-group
+ coalesce-id CDATA #IMPLIED
+ %display-nic;
+ %inherited-characteristics;
+>
+
+<!ATTLIST paragraph
+ %display-nic;
+ %inherited-characteristics;
+>
+
+<!ATTLIST paragraph-break
+ %display-nic;
+ %inherited-characteristics;
+>
+
+<!ATTLIST table-part
+ %display-nic;
+ %inherited-characteristics;
+>
+
+<!ENTITY % character-c "
+ char CDATA #IMPLIED
+ glyph-id CDATA #IMPLIED
+ drop-after-line-break %boolean; #IMPLIED
+ drop-unless-before-line-break %boolean; #IMPLIED
+ punct %boolean; #IMPLIED
+ space %boolean; #IMPLIED
+ input-tab %boolean; #IMPLIED
+ input-whitespace %boolean; #IMPLIED
+ record-end %boolean; #IMPLIED
+ break-before-priority NMTOKEN #IMPLIED
+ break-after-priority NMTOKEN #IMPLIED
+ math-font-posture %enum-or-boolean; #IMPLIED
+ math-class %enum; #IMPLIED
+ script CDATA #IMPLIED
+ %inherited-characteristics;">
+
+<!ATTLIST character %character-c;>
+<!ATTLIST radical.radical %character-c;>
+
+<!ATTLIST grid
+ grid-n-columns NMTOKEN #IMPLIED
+ grid-n-rows NMTOKEN #IMPLIED
+ %inherited-characteristics;
+>
+
+<!ATTLIST grid-cell
+ column-number NMTOKEN #IMPLIED
+ row-number NMTOKEN #IMPLIED
+ %inherited-characteristics;
+>
diff --git a/info/examples/lwc/ch7/inv1html.pl b/info/examples/lwc/ch7/inv1html.pl
new file mode 100644
index 0000000000..0f1e0d4e38
--- /dev/null
+++ b/info/examples/lwc/ch7/inv1html.pl
@@ -0,0 +1,61 @@
+########################################################################
+# SGMLSPL script produced automatically by the script sgmlspl.pl
+#
+# Document Type: inv1html.pl (for HTML/CSS formatting)
+# Edited by: mg (24 Aug 98)
+########################################################################
+
+use SGMLS; # Use the SGMLS package.
+use SGMLS::Output; # Use stack-based output.
+
+#
+# Document Handlers.
+#
+sgml('start', "<HTML>\n<HEAD>\n" .
+ "<TITLE> Invitation (sgmlpl/CSS formatting) </TITLE>\n" .
+ "<LINK href=\"invit.css\" rel=\"style-sheet\" type=\"text/css\">\n" .
+ "<!-- 24 August 1998 mg -->\n" .
+ "</HEAD>\n");
+sgml('end', "</HTML>");
+
+#
+# Element Handlers.
+#
+
+sgml('<invitation>', "<BODY>\n<H1>INVITATION</H1>\n");
+sgml('</invitation>', "</BODY>\n");
+
+sgml('<front>', "<P><TABLE>\n<TBODY>\n");
+sgml('</front>', "</TBODY>\n</TABLE>\n");
+
+sgml('<to>', "<TR><TD class=\"front\">To: </TD>\n<TD>");
+sgml('</to>', "</TD></TR>\n");
+
+sgml('<date>', "<TR><TD class=\"front\">When: </TD>\n<TD>");
+sgml('</date>', "</TD></TR>\n");
+
+sgml('<where>', "<TR><TD class=\"front\">Venue: </TD>\n<TD>");
+sgml('</where>', "</TD></TR>\n");
+
+sgml('<why>', "<TR><TD class=\"front\">Occasion: </TD>\n<TD>");
+sgml('</why>', "</TD></TR>\n");
+
+sgml('<body>', "");
+sgml('</body>', "");
+
+sgml('<par>', "<P>");
+sgml('</par>', "</P>\n");
+
+sgml('<emph>', "<EM>");
+sgml('</emph>', "</EM>");
+
+sgml('<back>', "");
+sgml('</back>', "");
+
+sgml('<signature>', "<P CLASS=\"signature\">");
+sgml('</signature>', "</P>\n");
+
+sgml('start_element',sub { die "Unknown element: " . $_[0]->name; });
+sgml('cdata',sub { output $_[0]; });
+
+1;
diff --git a/info/examples/lwc/ch7/inv2css.html.save b/info/examples/lwc/ch7/inv2css.html.save
new file mode 100644
index 0000000000..9615cdb76c
--- /dev/null
+++ b/info/examples/lwc/ch7/inv2css.html.save
@@ -0,0 +1,44 @@
+<HTML>
+<HEAD>
+<TITLE> Invitation (sgmlpl/CSS formatting) </TITLE>
+<LINK href="invit.css" rel="style-sheet" type="text/css">
+<!-- 24 August 1998 mg -->
+</HEAD>
+<BODY>
+<H1>INVITATION</H1>
+<P><TABLE>
+<TBODY>
+<TR><TD class="front">To: </TD>
+<TD>Anna, Bernard, Didier, Johanna</TD></TR>
+<TR><TD class="front">When: </TD>
+<TD>Next Friday Evening at 8 pm</TD></TR>
+<TR><TD class="front">Venue: </TD>
+<TD>The Web Cafe</TD></TR>
+<TR><TD class="front">Occasion: </TD>
+<TD>My first XML baby</TD></TR>
+</TBODY>
+</TABLE>
+<P>
+
+I would like to invite you all to celebrate
+
+the birth of <EM>Invitation</EM>, my
+
+first XML document child.
+
+</P>
+<P>
+
+Please do your best to come and join me next Friday
+
+evening. And, do not forget to bring your friends.
+
+</P>
+<P>
+
+I <EM>really</EM> look forward to see you soon!
+
+</P>
+<P CLASS="signature">Michel</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/info/examples/lwc/ch7/inv2html.pl b/info/examples/lwc/ch7/inv2html.pl
new file mode 100644
index 0000000000..42637a1276
--- /dev/null
+++ b/info/examples/lwc/ch7/inv2html.pl
@@ -0,0 +1,61 @@
+########################################################################
+# SGMLSPL script produced automatically by the script sgmlspl.pl
+#
+# Document Type: inv2html.pl (for HTML/CSS formatting)
+# Edited by: mg (25 Aug 1998)
+########################################################################
+
+use SGMLS; # Use the SGMLS package.
+use SGMLS::Output; # Use stack-based output.
+
+#
+# Document Handlers.
+#
+sgml('start', sub {
+ output "<HTML>\n<HEAD>\n";
+ output "<TITLE> Invitation (sgmlpl/CSS formatting) </TITLE>\n";
+ output "<LINK href=\"invit.css\" rel=\"style-sheet\" type=\"text/css\">\n";
+ output "<!-- 24 August 1998 mg -->\n";
+ output "</HEAD>\n";
+});
+sgml('end', "</HTML>");
+
+#
+# Element Handlers.
+#
+
+# Element: invitation
+sgml('<invitation>', sub {
+ my ($element,$event) = @_;
+ # First save the information for further use
+ # Local variables
+ my $date = $element->attribute('date')->value;
+ my $to = $element->attribute('to')->value;
+ my $where = $element->attribute('where')->value;
+ my $why = $element->attribute('why')->value;
+ # Global variable (saved for end of document)
+ $main::GLsig = $element->attribute('signature')->value;
+ # Output the HTML commands needed for the front matter
+ output "<BODY>\n<H1>INVITATION</H1>\n";
+ output "<P><TABLE>\n<TBODY>\n";
+ output "<TR><TD class=\"front\">To: </TD>\n<TD>$to</TD></TR>\n";
+ output "<TR><TD class=\"front\">When: </TD>\n<TD>$date</TD></TR>\n";
+ output "<TR><TD class=\"front\">Venue: </TD>\n<TD>$where</TD></TR>\n";
+ output "<TR><TD class=\"front\">Occasion: </TD>\n<TD>$why</TD></TR>\n";
+ output "</TBODY>\n</TABLE>\n";
+});
+
+sgml('</invitation>', sub{ # signature and end of document
+ output "<P CLASS=\"signature\">$main::GLsig</P>\n";
+ output "</BODY>\n";
+});
+
+# Elements: par and emph
+sgml('<par>', "<P>");
+sgml('</par>', "</P>\n");
+
+sgml('<emph>', "<EM>");
+sgml('</emph>', "</EM>");
+
+sgml('cdata',sub { output $_[0]; });
+1;
diff --git a/info/examples/lwc/ch7/inv2lat.pl b/info/examples/lwc/ch7/inv2lat.pl
new file mode 100644
index 0000000000..89e2f42015
--- /dev/null
+++ b/info/examples/lwc/ch7/inv2lat.pl
@@ -0,0 +1,76 @@
+########################################################################
+# SGMLSPL script produced automatically by the script sgmlspl.pl
+#
+# Document Type: invitation --> customization for LaTeX
+# Edited by: mg (August 14th 1998)
+########################################################################
+
+use SGMLS; # Use the SGMLS package.
+use SGMLS::Output; # Use stack-based output.
+
+#
+# Document Handlers.
+#
+sgml('start', sub {});
+sgml('end', sub {});
+
+#
+# Element Handlers.
+#
+
+# Element: invitation
+sgml('<invitation>', "\\documentclass[]{article}\n" .
+ "\\usepackage{invitation}\n" .
+ "\\begin{document}\n");
+sgml('</invitation>', "\\end{document}\n");
+
+# Element: front
+sgml('<front>', "\\begin{Front}\n");
+sgml('</front>', "\\end{Front}\n");
+
+# Element: to
+sgml('<to>', "\\To{");
+sgml('</to>', "}\n");
+
+# Element: date
+sgml('<date>', "\\Date{");
+sgml('</date>', "}\n");
+
+# Element: where
+sgml('<where>', "\\Where{");
+sgml('</where>', "}\n");
+
+# Element: why
+sgml('<why>', "\\Why{");
+sgml('</why>', "}\n");
+
+# Element: body
+sgml('<body>', "\\begin{Body}\n");
+sgml('</body>', "\\end{Body}\n");
+
+# Element: par
+sgml('<par>', "\\par ");
+sgml('</par>', "\n");
+
+# Element: emph
+sgml('<emph>', "\\emph{");
+sgml('</emph>', "}");
+
+# Element: back
+sgml('<back>', "\\begin{Back}\n");
+sgml('</back>', "\\end{Back}\n");
+
+# Element: signature
+sgml('<signature>', "\\Signature{");
+sgml('</signature>', "}\n");
+#
+# Default handlers
+#
+sgml('start_element',sub { die "Unknown element: " . $_[0]->name; });
+sgml('cdata',sub { output $_[0]; });
+sgml('re'," ");
+sgml('pi',sub { die "Unknown processing instruction: " . $_[0]; });
+sgml('entity',sub { die "Unknown external entity: " . $_[0]->name; });
+sgml('conforming','');
+
+1;
diff --git a/info/examples/lwc/ch7/inv3.xml b/info/examples/lwc/ch7/inv3.xml
new file mode 100644
index 0000000000..2080967a5d
--- /dev/null
+++ b/info/examples/lwc/ch7/inv3.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE invitation SYSTEM "invitation2.dtd">
+<invitation to="Anna, Bernard, Didier, Johanna"
+ date="Next Friday Evening at 8 pm"
+ where="The <emph>Web</emph> Cafe"
+ why="My first XML baby"
+ signature="Michel"
+>
+<par>
+I would like to invite you all to celebrate
+the birth of <emph>Invitation</emph>, my
+first XML document child.
+</par>
+<par>
+Please do your best to come and join me next Friday
+evening. And, do not forget to bring your friends.
+</par>
+<par>
+I <emph>really</emph> look forward to see you soon!
+</par>
+</invitation>
diff --git a/info/examples/lwc/ch7/invcss.html.save b/info/examples/lwc/ch7/invcss.html.save
new file mode 100644
index 0000000000..9615cdb76c
--- /dev/null
+++ b/info/examples/lwc/ch7/invcss.html.save
@@ -0,0 +1,44 @@
+<HTML>
+<HEAD>
+<TITLE> Invitation (sgmlpl/CSS formatting) </TITLE>
+<LINK href="invit.css" rel="style-sheet" type="text/css">
+<!-- 24 August 1998 mg -->
+</HEAD>
+<BODY>
+<H1>INVITATION</H1>
+<P><TABLE>
+<TBODY>
+<TR><TD class="front">To: </TD>
+<TD>Anna, Bernard, Didier, Johanna</TD></TR>
+<TR><TD class="front">When: </TD>
+<TD>Next Friday Evening at 8 pm</TD></TR>
+<TR><TD class="front">Venue: </TD>
+<TD>The Web Cafe</TD></TR>
+<TR><TD class="front">Occasion: </TD>
+<TD>My first XML baby</TD></TR>
+</TBODY>
+</TABLE>
+<P>
+
+I would like to invite you all to celebrate
+
+the birth of <EM>Invitation</EM>, my
+
+first XML document child.
+
+</P>
+<P>
+
+Please do your best to come and join me next Friday
+
+evening. And, do not forget to bring your friends.
+
+</P>
+<P>
+
+I <EM>really</EM> look forward to see you soon!
+
+</P>
+<P CLASS="signature">Michel</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/info/examples/lwc/ch7/invfo1.fop b/info/examples/lwc/ch7/invfo1.fop
new file mode 100644
index 0000000000..171530603b
--- /dev/null
+++ b/info/examples/lwc/ch7/invfo1.fop
@@ -0,0 +1,21 @@
+<fo:page-sequence font-family="serif" font-size="12pt" margin-top="15mm" margin-bottom="15mm" margin-left="15mm" margin-right="15mm" page-width="120mm" id="pageseq" xmlns:fo="http://www.w3.org/TR/WD-xsl/FO">
+
+<fo:display-sequence><fo:block font-family="sans-serif" font-size="24pt" font-weight="bold" text-align="center">INVITATION</fo:block><fo:list label-width="2cm"><fo:list-item id="listto"><fo:list-item-label font-style="italic">To:</fo:list-item-label><fo:list-item-body>Anna, Bernard, Didier, Johanna</fo:list-item-body></fo:list-item><fo:list-item id="listdate"><fo:list-item-label font-style="italic">When:</fo:list-item-label><fo:list-item-body>Next Friday Evening at 8 pm</fo:list-item-body></fo:list-item><fo:list-item id="listwhere"><fo:list-item-label font-style="italic">Venue:</fo:list-item-label><fo:list-item-body>The Web Cafe</fo:list-item-body></fo:list-item><fo:list-item id="listwhy"><fo:list-item-label font-style="italic">Occasion:</fo:list-item-label><fo:list-item-body>My first XML baby</fo:list-item-body></fo:list-item></fo:list></fo:display-sequence>
+
+
+<fo:block space-before="12pt">
+I would like to invite you all to celebrate
+the birth of <fo:inline-sequence font-style="italic">Invitation</fo:inline-sequence>, my
+first XML document child.
+</fo:block>
+<fo:block space-before="12pt">
+Please do your best to come and join me next Friday
+evening. And, do not forget to bring your friends.
+</fo:block>
+<fo:block space-before="12pt">
+I <fo:inline-sequence font-style="italic">really</fo:inline-sequence> look forward to see you soon!
+</fo:block>
+
+
+<fo:block space-before="12pt" font-weight="bold" text-align="right">From: Michel</fo:block>
+</fo:page-sequence> \ No newline at end of file
diff --git a/info/examples/lwc/ch7/invfo1.out b/info/examples/lwc/ch7/invfo1.out
new file mode 100644
index 0000000000..4265aef4b9
--- /dev/null
+++ b/info/examples/lwc/ch7/invfo1.out
@@ -0,0 +1,50 @@
+<fo:page-sequence font-family="serif" font-size="12pt"
+ margin-top="15mm" margin-bottom="15mm" margin-left="15mm"
+ margin-right="15mm" page-width="120mm" id="pageseq"
+ xmlns:fo="http://www.w3.org/XSL/Format/1.0">
+
+<fo:block font-family="sans-serif" font-size="24pt"
+ font-weight="bold" text-align="center">
+ INVITATION
+</fo:block>
+
+<fo:list label-width="2cm">
+ <fo:list-item id="listto">
+ <fo:list-item-label font-style="italic">To:</fo:list-item-label>
+ <fo:list-item-body>Anna, Bernard, Didier, Johanna</fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item id="listdate">
+ <fo:list-item-label font-style="italic">When:</fo:list-item-label>
+ <fo:list-item-body>Next Friday Evening at 8 pm</fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item id="listwhere">
+ <fo:list-item-label font-style="italic">Venue:</fo:list-item-label>
+ <fo:list-item-body>The Web Cafe</fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item id="listwhy">
+ <fo:list-item-label font-style="italic">Occasion:</fo:list-item-label>
+ <fo:list-item-body>My first XML baby</fo:list-item-body>
+ </fo:list-item>
+</fo:list>
+
+<fo:block space-before="12pt">
+ I would like to invite you all to celebrate the birth of
+ <fo:sequence font-style="italic">Invitation</fo:sequence>,
+ my first XML document child.
+</fo:block>
+
+<fo:block space-before="12pt">
+ Please do your best to come and join me next Friday
+ evening. And, do not forget to bring your friends.
+</fo:block>
+
+<fo:block space-before="12pt">
+ I <fo:sequence font-style="italic">really</fo:sequence>
+ look forward to see you soon!
+</fo:block>
+
+
+<fo:block space-before="12pt" font-weight="bold" text-align="right">
+From: Michel
+</fo:block>
+</fo:page-sequence> \ No newline at end of file
diff --git a/info/examples/lwc/ch7/invfo1.pdf b/info/examples/lwc/ch7/invfo1.pdf
new file mode 100644
index 0000000000..38f3df33b7
--- /dev/null
+++ b/info/examples/lwc/ch7/invfo1.pdf
@@ -0,0 +1,319 @@
+%PDF-1.2
+1 0 obj
+<< /Type /Info /Producer (FOP 0.5.1) >>
+endobj
+2 0 obj
+<< /Pages 17 0 R /Type /Catalog >>
+endobj
+3 0 obj
+<< /ProcSet [ /PDF /Text ] /Font << /F12 4 0 R /F11 5 0 R /F10 6 0 R /F9 7 0 R /F8 8 0 R /F7 9 0 R /F6 10 0 R /F5 11 0 R /F4 12 0 R /F3 13 0 R /F2 14 0 R /F1 15 0 R >> >>
+endobj
+4 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Courier-BoldOblique /Subtype /Type1 /Name /F12 >>
+endobj
+5 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Courier-Bold /Subtype /Type1 /Name /F11 >>
+endobj
+6 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Courier-Oblique /Subtype /Type1 /Name /F10 >>
+endobj
+7 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Courier /Subtype /Type1 /Name /F9 >>
+endobj
+8 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Times-BoldItalic /Subtype /Type1 /Name /F8 >>
+endobj
+9 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Times-Bold /Subtype /Type1 /Name /F7 >>
+endobj
+10 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Times-Italic /Subtype /Type1 /Name /F6 >>
+endobj
+11 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Times-Roman /Subtype /Type1 /Name /F5 >>
+endobj
+12 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Helvetica-BoldOblique /Subtype /Type1 /Name /F4 >>
+endobj
+13 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Helvetica-Bold /Subtype /Type1 /Name /F3 >>
+endobj
+14 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Helvetica-Oblique /Subtype /Type1 /Name /F2 >>
+endobj
+15 0 obj
+<< /Type /Font /Encoding /AdobeStandardEncoding /BaseFont /Helvetica /Subtype /Type1 /Name /F1 >>
+endobj
+16 0 obj
+<< /Length 2508 >>
+stream
+BT
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ /F5 12 Tf
+ 42 800 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=59][
+ 59 0 Td
+ /F3 24 Tf
+ 0 -12 Td
+ (INVITATION) Tj
+ 0 0 Td
+ -59 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ /F5 12 Tf
+ 0 -12 Td
+ 0 -12 Td
+ /F6 12 Tf
+ (To:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (Anna,) Tj
+ ( ) Tj
+ (Bernard,) Tj
+ ( ) Tj
+ (Didier,) Tj
+ ( ) Tj
+ (Johanna) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ /F6 12 Tf
+ (When:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (Next) Tj
+ ( ) Tj
+ (Friday) Tj
+ ( ) Tj
+ (Evening) Tj
+ ( ) Tj
+ (at) Tj
+ ( ) Tj
+ (8) Tj
+ ( ) Tj
+ (pm) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ /F6 12 Tf
+ (Venue:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (The) Tj
+ ( ) Tj
+ (Web) Tj
+ ( ) Tj
+ (Cafe) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ /F6 12 Tf
+ (Occasion:) Tj
+ 56 0 Td
+ /F5 12 Tf
+ (My) Tj
+ ( ) Tj
+ (first) Tj
+ ( ) Tj
+ (XML) Tj
+ ( ) Tj
+ (baby) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ -56 -12 Td
+ (I) Tj
+ ( ) Tj
+ (would) Tj
+ ( ) Tj
+ (like) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (invite) Tj
+ ( ) Tj
+ (you) Tj
+ ( ) Tj
+ (all) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (celebrate) Tj
+ ( ) Tj
+ (the) Tj
+ ( ) Tj
+ (birth) Tj
+ ( ) Tj
+ (of) Tj
+ ( ) Tj
+ /F6 12 Tf
+ -0 0 Td
+%]
+% vbox-movedown[linespacing=12][
+ 0 -12 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ (Invitation) Tj
+ /F5 12 Tf
+ (,) Tj
+ ( ) Tj
+ (my) Tj
+ ( ) Tj
+ (first) Tj
+ ( ) Tj
+ (XML) Tj
+ ( ) Tj
+ (document) Tj
+ ( ) Tj
+ (child.) Tj
+ ( ) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ 0 -12 Td
+ (Please) Tj
+ ( ) Tj
+ (do) Tj
+ ( ) Tj
+ (your) Tj
+ ( ) Tj
+ (best) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (come) Tj
+ ( ) Tj
+ (and) Tj
+ ( ) Tj
+ (join) Tj
+ ( ) Tj
+ (me) Tj
+ ( ) Tj
+ (next) Tj
+ ( ) Tj
+ (Friday) Tj
+ ( ) Tj
+ -0 0 Td
+%]
+% vbox-movedown[linespacing=12][
+ 0 -12 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ (evening.) Tj
+ ( ) Tj
+ (And,) Tj
+ ( ) Tj
+ (do) Tj
+ ( ) Tj
+ (not) Tj
+ ( ) Tj
+ (forget) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (bring) Tj
+ ( ) Tj
+ (your) Tj
+ ( ) Tj
+ (friends.) Tj
+ ( ) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=0][
+ 0 0 Td
+ 0 -12 Td
+ (I) Tj
+ ( ) Tj
+ /F6 12 Tf
+ (really) Tj
+ /F5 12 Tf
+ ( ) Tj
+ (look) Tj
+ ( ) Tj
+ (forward) Tj
+ ( ) Tj
+ (to) Tj
+ ( ) Tj
+ (see) Tj
+ ( ) Tj
+ (you) Tj
+ ( ) Tj
+ (soon!) Tj
+ ( ) Tj
+ 0 0 Td
+ -0 0 Td
+%]
+% vbox-box[extra-start-indent=185][
+ 185 0 Td
+ /F7 12 Tf
+ 0 -12 Td
+ (From:) Tj
+ ( ) Tj
+ (Michel) Tj
+ 0 0 Td
+ -185 0 Td
+%]
+ET
+endstream
+endobj
+17 0 obj
+<< /Kids [ 18 0 R ] /Type /Pages /MediaBox [ 0 0 340 842 ] /Count 1 >>
+endobj
+18 0 obj
+<< /Type /Page /Contents 16 0 R /Parent 17 0 R /Resources 3 0 R >>
+endobj
+xref
+0 19
+0000000000 65535 f
+0000000009 00000 n
+0000000064 00000 n
+0000000114 00000 n
+0000000300 00000 n
+0000000424 00000 n
+0000000541 00000 n
+0000000661 00000 n
+0000000772 00000 n
+0000000892 00000 n
+0000001006 00000 n
+0000001123 00000 n
+0000001239 00000 n
+0000001365 00000 n
+0000001484 00000 n
+0000001606 00000 n
+0000001720 00000 n
+0000004280 00000 n
+0000004367 00000 n
+trailer
+<<
+/Size 19
+/Root 2 0 R
+/Info 1 0 R
+>>
+startxref
+4450
+%%EOF
diff --git a/info/examples/lwc/ch7/invfo1.xsl b/info/examples/lwc/ch7/invfo1.xsl
new file mode 100644
index 0000000000..8341d018c7
--- /dev/null
+++ b/info/examples/lwc/ch7/invfo1.xsl
@@ -0,0 +1,80 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ xmlns:fo="http://www.w3.org/XSL/Format/1.0"
+ result-ns="fo"
+ default-space="">
+<xsl:variable name="Fontsize">12pt</xsl:variable>
+<xsl:template name="listitem">
+ <xsl:param-variable name="labeltext">labeltext</xsl:param-variable>
+ <xsl:param-variable name="itemid">itemid</xsl:param-variable>
+ <xsl:param-variable name="itemtext">itemtext</xsl:param-variable>
+ <fo:list-item id="{$itemid}">
+ <fo:list-item-label font-style="italic">
+ <xsl:value-of select="$labeltext"/>
+ <xsl:text>:</xsl:text>
+ </fo:list-item-label>
+ <fo:list-item-body>
+ <xsl:value-of select="$itemtext"/>
+ </fo:list-item-body>
+ </fo:list-item>
+</xsl:template>
+
+<xsl:template match='/'>
+ <fo:page-sequence font-family="serif" font-size="{$Fontsize}"
+ margin-top="15mm" margin-bottom="15mm"
+ margin-left="15mm" margin-right="15mm"
+ page-width="120mm" id="pageseq">
+ <xsl:apply-templates/>
+ </fo:page-sequence>
+</xsl:template>
+
+<xsl:template match="invitation/front">
+<fo:block font-family="sans-serif" font-size="24pt"
+ font-weight="bold" text-align="center">
+ <xsl:text>INVITATION</xsl:text>
+</fo:block>
+<fo:list label-width="2cm">
+ <xsl:call-template name="listitem">
+ <xsl:param name="labeltext">To</xsl:param>
+ <xsl:param name="itemid">listto</xsl:param>
+ <xsl:param name="itemtext"><xsl:value-of select="to"/></xsl:param>
+ </xsl:call-template>
+ <xsl:call-template name="listitem">
+ <xsl:param name="labeltext">When</xsl:param>
+ <xsl:param name="itemid">listdate</xsl:param>
+ <xsl:param name="itemtext"><xsl:value-of select="date"/></xsl:param>
+ </xsl:call-template>
+ <xsl:call-template name="listitem">
+ <xsl:param name="labeltext">Venue</xsl:param>
+ <xsl:param name="itemid">listwhere</xsl:param>
+ <xsl:param name="itemtext" expr="where"/>
+ </xsl:call-template>
+ <xsl:call-template name="listitem">
+ <xsl:param name="labeltext">Occasion</xsl:param>
+ <xsl:param name="itemid">listwhy</xsl:param>
+ <xsl:param name="itemtext"><xsl:value-of select="why"/></xsl:param>
+ </xsl:call-template>
+</fo:list>
+</xsl:template>
+
+<xsl:template match="invitation/body/par">
+ <fo:block space-before="{$Fontsize}">
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>
+
+<xsl:template match="invitation/body/par/emph">
+ <fo:sequence font-style="italic">
+ <xsl:apply-templates/>
+ </fo:sequence>
+</xsl:template>
+
+<xsl:template match="invitation/back">
+<fo:block space-before="{$Fontsize}"
+ font-weight="bold" text-align="right">
+ <xsl:text>From: </xsl:text>
+ <xsl:value-of select="signature"/>
+</fo:block>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/info/examples/lwc/ch7/invhtml.dsl b/info/examples/lwc/ch7/invhtml.dsl
new file mode 100644
index 0000000000..6f4b7ac5b4
--- /dev/null
+++ b/info/examples/lwc/ch7/invhtml.dsl
@@ -0,0 +1,90 @@
+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style-Sheet//EN">
+<style-sheet>
+<style-specification>
+<style-specification-body>
+(declare-flow-object-class element
+ "UNREGISTERED::James Clark//Flow Object Class::element")
+(declare-flow-object-class empty-element
+ "UNREGISTERED::James Clark//Flow Object Class::empty-element")
+(declare-flow-object-class document-type
+ "UNREGISTERED::James Clark//Flow Object Class::document-type")
+
+(define FontSize 12pt)
+(root
+ (make simple-page-sequence
+ left-margin: 25mm
+ page-width: 205mm
+ right-margin: 25mm
+ (make sequence
+ font-size: FontSize
+ line-spacing: FontSize
+ (make document-type
+ name: "HTML"
+ public-id: "-//W3C//DTD HTML 3.2//EN")
+ (make element gi: "HEAD"
+ (make element gi: "TITLE"
+ (literal "Invitation (XML to HTML transformation)"))
+ (make empty-element gi: "LINK"
+ attributes: (list (list "href" "invit.css")
+ (list "rel" "stylesheet")
+ (list "type" "text/css"))))
+ (make element gi: "BODY"
+ (make sequence
+ (make element gi: "H1"
+ (literal "INVITATION"))
+ (process-children))))))
+
+(element (front)
+ (make element gi: "TABLE"
+ attributes: (list (list "border" "5")
+ (list "frame" "hsides")
+ (list "rules" "none")
+ (list "width" "100%"))
+ (process-children)))
+(element (front date)
+ (make element gi: "TR"
+ (make sequence
+ (make element gi: "TD"
+ attributes: (list (list "class" "front"))
+ (literal "When: "))
+ (make element gi: "TD"
+ (process-children)))))
+(element (front to)
+ (make element gi: "TR"
+ (make sequence
+ (make element gi: "TD"
+ attributes: (list (list "class" "front"))
+ (literal "To: "))
+ (make element gi: "TD"
+ (process-children)))))
+(element (front where)
+ (make element gi: "TR"
+ (make sequence
+ (make element gi: "TD"
+ attributes: (list (list "class" "front"))
+ (literal "Venue: "))
+ (make element gi: "TD"
+ (process-children)))))
+(element (front why)
+ (make element gi: "TR"
+ (make sequence
+ (make element gi: "TD"
+ attributes: (list (list "class" "front"))
+ (literal "Occasion: "))
+ (make element gi: "TD"
+ (process-children)))))
+(element (body par)
+ (make element gi: "P"
+ (process-children)))
+(element emph
+ (make element gi: "EM"
+ (process-children)))
+(element (back signature)
+ (make element gi: "P"
+ attributes: (list (list "class" "signature"))
+ (make sequence
+ (literal "From: ")
+ (process-children))))
+</style-specification-body>
+</style-specification>
+</style-sheet>
diff --git a/info/examples/lwc/ch7/invhtml2.xsl b/info/examples/lwc/ch7/invhtml2.xsl
new file mode 100644
index 0000000000..dba1cf779f
--- /dev/null
+++ b/info/examples/lwc/ch7/invhtml2.xsl
@@ -0,0 +1,43 @@
+<?xml version='1.0'?>
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ xmlns="http://www.w3.org/TR/REC-html40"
+ result-ns="">
+
+<xsl:template match="/">
+<html>
+<head>
+<title> Invitation (XSL/CSS formatting) </title>
+<link href="invit.css" rel="stylesheet" type="text/css"/>
+<!-- 12 November 1998 mg -->
+</head>
+<body>
+<h1>INVITATION</h1>
+<table>
+<tbody>
+<tr><td class="front">To: </td>
+<td><xsl:value-of select="@to"/></td></tr>
+<tr><td class="front">When: </td>
+<td><xsl:value-of select="@date"/></td></tr>
+<tr><td class="front">Venue: </td>
+<td><xsl:value-of select="@where"/></td></tr>
+<tr><td class="front">Occasion: </td>
+<td><xsl:value-of select="@why"/></td></tr>
+</tbody>
+</table>
+<xsl:apply-templates/>
+<p class="signature"><xsl:value-of select="@signature"/></p>
+</body>
+</html>
+</xsl:template>
+
+<xsl:template match="invitation/par">
+<p><xsl:apply-templates/></p>
+</xsl:template>
+
+<xsl:template match="invitation/par/emph">
+<em><xsl:apply-templates/></em>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/info/examples/lwc/ch7/invit.css b/info/examples/lwc/ch7/invit.css
new file mode 100644
index 0000000000..e28eb44d06
--- /dev/null
+++ b/info/examples/lwc/ch7/invit.css
@@ -0,0 +1,31 @@
+/* CSS stylesheet for invitation1 in HTML */
+BODY {margin-top: 1em; /* global page parameters */
+ margin-bottom: 1em;
+ margin-left: 1em;
+ margin-right: 1em;
+ font-family: serif;
+ line-height: 1.1;
+ color: black;
+}
+H1 {text-align: center; /* for global title */
+ font-size: x-large;
+}
+P {text-align: justify; /* paragraphs in body */
+ margin-top: 1em;
+}
+TABLE { border-width: 0pt }
+TBODY { border-width: 0pt }
+TD[class="front"] { /* table data in front matter */
+ text-align: left;
+ font-weight: bold;
+}
+TD.front { /* table data in front matter */
+ text-align: left;
+ font-weight: bold;
+}
+EM {font-style: italic; /* emphasis in body */
+}
+P.signature { /* signature */
+ text-align: right;
+ font-weight: bold;
+}
diff --git a/info/examples/lwc/ch7/invitation.dsl b/info/examples/lwc/ch7/invitation.dsl
new file mode 100644
index 0000000000..fb1da6b164
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation.dsl
@@ -0,0 +1,66 @@
+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style-Sheet//EN">
+<style-sheet>
+<style-specification>
+<style-specification-body>
+(define FontSize 12pt)
+(root
+ (make simple-page-sequence
+ left-margin: 25mm
+ page-width: 205mm
+ right-margin: 25mm
+ (make scroll
+ font-size: FontSize
+ line-spacing: FontSize
+ (process-children)
+ )
+ )
+)
+(element (front date)
+ (make paragraph
+ (literal "When: ")
+ (process-children)
+ )
+)
+(element (front to)
+ (make paragraph
+ (literal "To: ")
+ (process-children)
+ )
+)
+(element (front where)
+ (make paragraph
+ (literal "Venue: ")
+ (process-children)
+ )
+)
+(element (front why)
+ (make paragraph
+ (literal "Occasion: ")
+ (process-children)
+ )
+)
+(element (body par)
+ (make paragraph
+ quadding: 'justify
+ font-size: FontSize
+ space-before: FontSize
+ (process-children)
+ )
+)
+(element emph
+ (make sequence
+ font-posture: 'italic
+ (process-children)
+ )
+)
+(element (back signature)
+ (make paragraph
+ quadding: 'justify
+ space-before: FontSize
+ (literal "From: ")
+ (process-children)
+ )
+)
+</style-specification-body>
+</style-specification>
+</style-sheet>
diff --git a/info/examples/lwc/ch7/invitation.dtd b/info/examples/lwc/ch7/invitation.dtd
new file mode 100644
index 0000000000..ad8df55047
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation.dtd
@@ -0,0 +1,14 @@
+<!-- invitation DTD -->
+<!-- May 26th 1998 mg -->
+<!ELEMENT invitation (front, body, back) >
+<!ELEMENT front (to, date, where, why?) >
+<!ELEMENT date (#PCDATA) >
+<!ELEMENT to (#PCDATA) >
+<!ELEMENT where (#PCDATA) >
+<!ELEMENT why (#PCDATA) >
+<!ELEMENT body (par+) >
+<!ELEMENT par (#PCDATA|emph)* >
+<!ELEMENT emph (#PCDATA) >
+<!ELEMENT back (signature) >
+<!ELEMENT signature (#PCDATA) >
+
diff --git a/info/examples/lwc/ch7/invitation.fot b/info/examples/lwc/ch7/invitation.fot
new file mode 100644
index 0000000000..19ac1e9369
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation.fot
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<fot>
+<a name="0"/>
+<a name="1"/>
+<a name="2"/>
+<text>Anna, Bernard, Didier, Johanna</text>
+<a name="3"/>
+<text>Next Friday Evening at 8 pm</text>
+<a name="4"/>
+<text>The Web Cafe</text>
+<a name="5"/>
+<text>My first XML baby</text>
+<a name="6"/>
+<a name="7"/>
+<text>
+I would like to invite you all to celebrate
+the birth of </text>
+<a name="8"/>
+<text>Invitation</text>
+<text>, my
+first XML document child.
+</text>
+<a name="9"/>
+<text>
+Please do your best to come and join me next Friday
+evening. And, do not forget to bring your friends.
+</text>
+<a name="10"/>
+<text>
+I </text>
+<a name="11"/>
+<text>really</text>
+<text> look forward to see you soon!
+</text>
+<a name="12"/>
+<a name="13"/>
+<text>Michel</text>
+</fot>
diff --git a/info/examples/lwc/ch7/invitation.sty b/info/examples/lwc/ch7/invitation.sty
new file mode 100644
index 0000000000..d01bf822bc
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation.sty
@@ -0,0 +1,30 @@
+% invitation.sty
+% Package to format invitation.xml
+\setlength{\parskip}{1ex}
+\setlength{\parindent}{0pt}
+\pagestyle{empty}%% Turn off page numbering
+\RequirePackage{array}
+\newenvironment{Front}%
+ {\begin{center}\huge \sffamily Memorandum\end{center}
+ \begin{flushleft}
+ \begin{tabular}{@{}>{\bfseries}p{.2\linewidth}@{}p{.8\linewidth}@{}}\hline
+ }
+ {To whom: & \@To \\
+ Occasion: & \@Why \\
+ Venue: & \@Where \\
+ When: & \@Date \\\hline
+ \end{tabular}
+ \end{flushleft}
+ }
+\newenvironment{Body}{\vspace*{\parskip}}{\vspace*{\parskip}}
+\newenvironment{Back}
+ {\begin{flushleft}}
+ {\hspace*{.5\linewidth}\fbox{\emph{\@Sig}}
+ \end{flushleft}
+ }
+\newcommand{\To}[1]{\gdef\@To{#1}}
+\newcommand{\Date}[1]{\gdef\@Date{#1}}
+\newcommand{\Where}[1]{\gdef\@Where{#1}}
+\newcommand{\Why}[1]{\gdef\@Why{#1}}
+\newcommand{\Signature}[1]{\gdef\@Sig{#1}}
+\endinput \ No newline at end of file
diff --git a/info/examples/lwc/ch7/invitation.tex.save b/info/examples/lwc/ch7/invitation.tex.save
new file mode 100644
index 0000000000..12ae67767f
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation.tex.save
@@ -0,0 +1,27 @@
+\documentclass[]{article}
+\usepackage{invitation}
+\begin{document}
+\begin{Front}
+\To{Anna, Bernard, Didier, Johanna}
+\Date{Next Friday Evening at 8 pm}
+\Where{The Web Cafe}
+\Why{My first XML baby}
+\end{Front}
+\begin{Body}
+\par
+I would like to invite you all to celebrate
+the birth of \emph{Invitation}, my
+first XML document child.
+
+\par
+Please do your best to come and join me next Friday
+evening. And, do not forget to bring your friends.
+
+\par
+I \emph{really} look forward to see you soon!
+
+\end{Body}
+\begin{Back}
+\Signature{Michel}
+\end{Back}
+\end{document}
diff --git a/info/examples/lwc/ch7/invitation.xml b/info/examples/lwc/ch7/invitation.xml
new file mode 100644
index 0000000000..25ca2c1830
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation.xml
@@ -0,0 +1,29 @@
+<!DOCTYPE invitation SYSTEM "invitation.dtd">
+<invitation>
+<!-- ++++ The header part of the document ++++ -->
+<front>
+<to>Anna, Bernard, Didier, Johanna</to>
+<date>Next Friday Evening at 8 pm</date>
+<where>The Web Cafe</where>
+<why>My first XML baby</why>
+</front>
+<!-- +++++ The main part of the document +++++ -->
+<body>
+<par>
+I would like to invite you all to celebrate
+the birth of <emph>Invitation</emph>, my
+first XML document child.
+</par>
+<par>
+Please do your best to come and join me next Friday
+evening. And, do not forget to bring your friends.
+</par>
+<par>
+I <emph>really</emph> look forward to see you soon!
+</par>
+</body>
+<!-- +++ The closing part of the document ++++ -->
+<back>
+<signature>Michel</signature>
+</back>
+</invitation>
diff --git a/info/examples/lwc/ch7/invitation2.dtd b/info/examples/lwc/ch7/invitation2.dtd
new file mode 100644
index 0000000000..c9a136de64
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation2.dtd
@@ -0,0 +1,15 @@
+<!-- invitation2 DTD -->
+<!-- August 14th 1998 mg -->
+<!ENTITY % i18n "xml:lang NMTOKEN #IMPLIED">
+<!ELEMENT invitation (par+)>
+<!ATTLIST invitation
+ %i18n;
+ date CDATA #REQUIRED
+ to CDATA #REQUIRED
+ signature CDATA #REQUIRED
+ where CDATA #REQUIRED
+ why CDATA #IMPLIED
+>
+<!ELEMENT par (#PCDATA|emph)*>
+<!ELEMENT emph (#PCDATA)>
+
diff --git a/info/examples/lwc/ch7/invitation2.xml b/info/examples/lwc/ch7/invitation2.xml
new file mode 100644
index 0000000000..877af219f9
--- /dev/null
+++ b/info/examples/lwc/ch7/invitation2.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE invitation SYSTEM "invitation2.dtd">
+<invitation to="Anna, Bernard, Didier, Johanna"
+ date="Next Friday Evening at 8 pm"
+ where="The Web Cafe"
+ why="My first XML baby"
+ signature="Michel"
+>
+<par>
+I would like to invite you all to celebrate
+the birth of <emph>Invitation</emph>, my
+first XML document child.
+</par>
+<par>
+Please do your best to come and join me next Friday
+evening. And, do not forget to bring your friends.
+</par>
+<par>
+I <emph>really</emph> look forward to see you soon!
+</par>
+</invitation>
diff --git a/info/examples/lwc/ch7/invitationfr.sty b/info/examples/lwc/ch7/invitationfr.sty
new file mode 100644
index 0000000000..68dedd1c10
--- /dev/null
+++ b/info/examples/lwc/ch7/invitationfr.sty
@@ -0,0 +1,50 @@
+% invitation.sty
+% Package to format invitation.xml
+\setlength{\textwidth}{22pc}
+\setlength{\parskip}{1ex}
+\setlength{\parindent}{0pt}
+\pagestyle{empty}%% Turn off page numbering
+\RequirePackage{array,calc}
+\newcommand{\ToTitle}{To whom}
+\newcommand{\WhyTitle}{Occasion}
+\newcommand{\WhereTitle}{Venue}
+\newcommand{\DateTitle}{When}
+\newcommand{\SignatureTitle}{From}
+\DeclareOption{francais}{% French text for fixed texts
+ \renewcommand{\ToTitle}{À}
+ \renewcommand{\WhyTitle}{À l'occasion de}
+ \renewcommand{\WhereTitle}{Où}
+ \renewcommand{\DateTitle}{Quand}
+ \renewcommand{\SignatureTitle}{De la part de}}
+\newenvironment{Front}%
+ {\begin{center}
+ \Huge\sffamily INVITATION
+ \end{center}
+ }
+ {\begin{flushleft}
+ \rule{\linewidth}{1pt}\\[2mm]
+ \begin{tabular}{@{}>{\bfseries}ll@{}}
+ \ToTitle: & \@To \\
+ \WhyTitle: & \@Why \\
+ \WhereTitle: & \@Where \\
+ \DateTitle: & \@Date
+ \end{tabular}\\[2mm]
+ \rule{\linewidth}{1pt}
+ \end{flushleft}
+ }
+\newenvironment{Body}{\vspace*{\parskip}}{\vspace*{\parskip}}
+\newenvironment{Back}
+ {\begin{flushleft}}
+ {\hspace*{.5\linewidth}\fbox{\SignatureTitle: \emph{\@Sig}}
+ \end{flushleft}
+ }
+\newcommand{\To}[1]{\gdef\@To{#1}}
+\newcommand{\Date}[1]{\gdef\@Date{#1}}
+\newcommand{\Where}[1]{\gdef\@Where{#1}}
+\newcommand{\Why}[1]{\gdef\@Why{#1}}
+\newcommand{\Signature}[1]{\gdef\@Sig{#1}}
+
+\ProcessOptions
+
+\endinput
+
diff --git a/info/examples/lwc/ch7/invlat1.xsl b/info/examples/lwc/ch7/invlat1.xsl
new file mode 100644
index 0000000000..13783ed374
--- /dev/null
+++ b/info/examples/lwc/ch7/invlat1.xsl
@@ -0,0 +1,63 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ default-space="strip"
+ result-ns="">
+
+<xsl:template match="invitation">
+<xsl:text>\documentclass[]{article}
+\usepackage{invitation}
+\begin{document}
+</xsl:text>
+<xsl:apply-templates/>
+<xsl:text>\end{document}
+</xsl:text>
+</xsl:template>
+
+<xsl:template match="invitation/front">
+<xsl:text>\begin{Front}
+\To{</xsl:text>
+<xsl:value-of select="to"/>
+<xsl:text>}
+\Date{</xsl:text>
+<xsl:value-of select="date"/>
+<xsl:text>}
+\Where{</xsl:text>
+<xsl:value-of select="where"/>
+<xsl:text>}
+\Why{</xsl:text>
+<xsl:value-of select="why"/>
+<xsl:text>}
+\end{Front}
+</xsl:text>
+</xsl:template>
+
+<xsl:template match="invitation/body">
+<xsl:text>\begin{Body}
+</xsl:text>
+ <xsl:apply-templates/>
+<xsl:text>\end{Body}
+</xsl:text>
+</xsl:template>
+
+<xsl:template match="invitation/body/par">
+<xsl:text>\par</xsl:text>
+<xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="invitation/body/par/emph">
+<xsl:text>\emph{</xsl:text>
+<xsl:apply-templates/>
+<xsl:text>}</xsl:text>
+</xsl:template>
+
+<xsl:template match="invitation/back">
+<xsl:text>\begin{Back}
+\Signature{</xsl:text>
+<xsl:value-of select="signature"/>
+<xsl:text>}
+\end{Back}
+</xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/info/examples/lwc/ch7/invtab1.dsl b/info/examples/lwc/ch7/invtab1.dsl
new file mode 100644
index 0000000000..3d7afc7d5b
--- /dev/null
+++ b/info/examples/lwc/ch7/invtab1.dsl
@@ -0,0 +1,82 @@
+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style-Sheet//EN">
+<style-sheet>
+<style-specification>
+<style-specification-body>
+
+(define FontSize 12pt)
+
+(root
+ (make simple-page-sequence
+ left-margin: 2cm
+ page-width: 15cm
+ right-margin: 2cm
+ (make scroll
+ font-size: FontSize
+ (process-children))))
+
+(element front
+ (make sequence
+ (make paragraph
+ quadding: 'center
+ space-before: 20pt
+ font-weight: 'bold
+ font-size: 24pt
+ (literal "INVITATION"))
+ (make table
+ table-border: #f ; no border
+ display-alignment: 'start
+ space-before: 20pt
+ (make table-part
+ (make table-column width: 25mm)
+ (make table-column width: 10cm)
+ (process-children)))))
+(element (front date)
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "When:")))
+ (make table-cell
+ (process-children))))
+(element (front to)
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "To:")))
+ (make table-cell
+ (process-children))))
+(element (front where)
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "Venue:")))
+ (make table-cell
+ (process-children))))
+(element (front why)
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "Occasion:")))
+ (make table-cell
+ (process-children))))
+
+(element (body par)
+ (make paragraph
+ quadding: 'justify
+ font-size: FontSize
+ space-before: FontSize
+ (process-children)))
+(element emph
+ (make sequence
+ font-posture: 'italic
+ (process-children)))
+
+(element (back signature)
+ (make paragraph
+ quadding: 'end
+ space-before: FontSize
+ (literal "From: ")
+ (process-children)))
+
+</style-specification-body>
+</style-specification>
+</style-sheet>
diff --git a/info/examples/lwc/ch7/invtab2.dsl b/info/examples/lwc/ch7/invtab2.dsl
new file mode 100644
index 0000000000..eac8c01392
--- /dev/null
+++ b/info/examples/lwc/ch7/invtab2.dsl
@@ -0,0 +1,75 @@
+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style-Sheet//EN">
+<style-sheet>
+<style-specification>
+<style-specification-body>
+(define FontSize 12pt)
+(root
+ (make simple-page-sequence
+ left-margin: 1cm
+ page-width: 10cm
+ right-margin: 1cm
+ (make scroll
+ font-size: FontSize
+ (process-children))))
+(element invitation
+ (make sequence
+ (make paragraph
+ quadding: 'center
+ space-before: 20pt
+ font-weight: 'bold
+ font-size: 24pt
+ (literal "INVITATION"))
+ (make table
+ table-border: #f ; no border
+ display-alignment: 'start
+ space-before: 20pt
+ (make table-part
+ (make table-column width: 25mm)
+ (make table-column width: 10cm)
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "When:")))
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal (attribute-string "date")))))
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "To:")))
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal (attribute-string "to")))))
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "Venue:")))
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal (attribute-string "where")))))
+ (make table-row
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal "Occasion:")))
+ (make table-cell
+ (make paragraph quadding: 'start
+ (literal (attribute-string "why")))))))
+ (process-children)
+ (make paragraph
+ quadding: 'end
+ space-before: FontSize
+ (literal "From: "
+ (attribute-string "signature")))))
+(element par
+ (make paragraph
+ quadding: 'justify
+ font-size: FontSize
+ space-before: FontSize
+ (process-children-trim)))
+(element emph
+ (make sequence
+ font-posture: 'italic
+ (process-children-trim)))
+</style-specification-body>
+</style-specification>
+</style-sheet>
diff --git a/info/examples/lwc/ch7/makesum.xml b/info/examples/lwc/ch7/makesum.xml
new file mode 100644
index 0000000000..a6cfe52ae7
--- /dev/null
+++ b/info/examples/lwc/ch7/makesum.xml
@@ -0,0 +1,5 @@
+<makesum>
+<real>3.0</real>
+<real>0.14159</real>
+<real>.0000026536</real>
+</makesum>
diff --git a/info/examples/lwc/ch7/makesum.xsl b/info/examples/lwc/ch7/makesum.xsl
new file mode 100644
index 0000000000..4dc413f082
--- /dev/null
+++ b/info/examples/lwc/ch7/makesum.xsl
@@ -0,0 +1,16 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" default-space="strip">
+
+<xsl:template match="makesum">
+ <xsl:invoke classid="java:com.jclark.xsl.sax.TextFileOutputFilter">
+ <xsl:arg name="file" value="sum.out"/>
+ <xsl:invoke classid="java:com.jclark.xsl.sax.TotalFilter">
+ <xsl:apply-templates/>
+ </xsl:invoke>
+ </xsl:invoke>
+</xsl:template>
+
+<xsl:template match="real">
+ <number><xsl:apply-templates/></number>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/info/examples/lwc/ch7/sectionexa.xml b/info/examples/lwc/ch7/sectionexa.xml
new file mode 100644
index 0000000000..9d73bc1793
--- /dev/null
+++ b/info/examples/lwc/ch7/sectionexa.xml
@@ -0,0 +1,22 @@
+<article>
+ <title>This is the article's title</title>
+ <author>Michel Goossens</author>
+ <author>Sebastian Rahtz</author>
+ <abstract>A <emph>short</emph> description of the contents</abstract>
+ <section sectid="S1">
+ <stitle>First section title</stitle>
+ <par ident="first">The first paragraph for this section.</par>
+ <par ident="normal">A normal paragraph with <emph>emphasised</emph> text.</par>
+ <par>Here we have <emph>no</emph> attribute.</par>
+ <par ident="last">This is the end of the section.</par>
+ </section>
+ <section sectid="S2">
+ <stitle>Second section title</stitle>
+ <par ident="first">The first paragraph for this section.</par>
+ <par>Here we <emph>also</emph> have <emph>no</emph> attribute.</par>
+ <par ident="normal" id="special">A normal paragraph with
+ <emph>emphasised</emph> text.</par>
+ <par>Another attribute-less paragraph.</par>
+ <par ident="last">This is the end of the section.</par>
+ </section>
+</article>
diff --git a/info/examples/lwc/ch7/sectionexa.xsl b/info/examples/lwc/ch7/sectionexa.xsl
new file mode 100644
index 0000000000..5012fea8e7
--- /dev/null
+++ b/info/examples/lwc/ch7/sectionexa.xsl
@@ -0,0 +1,72 @@
+<?xml version='1.0'?>
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ result-ns="">
+<xsl:template match="/">
+ <xsl:text>(*root*)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/*root*)</xsl:text>
+</xsl:template>
+<xsl:template match="*" priority="-1">
+ <xsl:text>(*)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/*)</xsl:text>
+</xsl:template>
+<xsl:template match="par">
+ <xsl:text>(T1)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/T1)</xsl:text>
+</xsl:template>
+<xsl:template match="par[@ident]" priority="1">
+ <xsl:text>(T2)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/T2)</xsl:text>
+</xsl:template>
+<xsl:template match="par[@ident='first']" priority="2">
+ <xsl:text>(T3)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/T3)</xsl:text>
+</xsl:template>
+<xsl:template match="section[@sectid='S2']
+ /par[@ident='normal' and @id='special']">
+ <xsl:text>(T4)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/T4)</xsl:text>
+</xsl:template>
+<xsl:template match="section[position()=last()]">
+ <xsl:text>(P1)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/P1)</xsl:text>
+</xsl:template>
+<xsl:template match="section[position()>1]/par[position()=1]">
+ <xsl:text>(P2)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/P2)</xsl:text>
+</xsl:template>
+<xsl:template match="author">
+ <xsl:text>(A1)</xsl:text>
+ <xsl:text>author 1: </xsl:text>
+ <xsl:text>(/A1)</xsl:text>
+ <xsl:apply-templates/>
+</xsl:template>
+<xsl:template match="author[position()=last()]" priority="1">
+ <xsl:text>(A2)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/A2)</xsl:text>
+</xsl:template>
+<xsl:template match="*[position()=1 and position()=last()]" priority="1">
+ <xsl:text>(WD)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/WD)</xsl:text>
+</xsl:template>
+<xsl:template match="emph[position()=1 and position()=last()]" priority="1">
+ <xsl:text>(E1)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/E1)</xsl:text>
+</xsl:template>
+<xsl:template match="emph[not(position()=1 and position()=last())]" priority="1">
+ <xsl:text>(E2)</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>(/E2)</xsl:text>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/info/examples/lwc/ch7/sgmlspl.pl b/info/examples/lwc/ch7/sgmlspl.pl
new file mode 100644
index 0000000000..c91a6cb004
--- /dev/null
+++ b/info/examples/lwc/ch7/sgmlspl.pl
@@ -0,0 +1,317 @@
+#!/usr/bin/perl
+########################################################################
+# sgmlspl: a simple SGML postprocesser for the SGMLS and NSGMLS
+# parsers (requires SGMLS.pm library).
+#
+# Copyright (c) 1995 by David Megginson <dmeggins@aix1.uottawa.ca>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Log: sgmlspl.pl,v $
+# Revision 1.8 1995/12/03 21:46:31 david
+# Eliminated all use of the SGMLS_Event::key method.
+#
+# Revision 1.7 1995/11/15 20:22:24 david
+# Changed "use Output" to "use SGMLS::Output". Qualified the STDIN
+# filehandle for the SGMLS object with the main:: package name.
+#
+# Revision 1.6 1995/08/12 16:15:14 david
+# Revised version for 1.01 distribution.
+#
+# Revision 1.5 1995/04/27 11:52:25 david
+# Changed 'print' to 'main::output' for re handler; empty string
+# translates into an empty sub {} rather than a sub printing an empty
+# string; instead of evaluating every argument as a perl script, take
+# only the first as a perl script and the rest as its arguments; allow
+# empty scripts or scripts which do not end with '1;'; pass the event
+# itself as the second argument to each handler, after the event data.
+#
+# Revision 1.4 1995/04/23 14:44:58 david
+# Use the Output package. Fixed the $version variable.
+#
+# Revision 1.3 1995/04/22 21:02:49 david
+# Added some missing 'last SWITCH;' statements in the sgmls function.
+#
+# Revision 1.2 1995/04/22 20:58:48 david
+# Added $SGMLS_PL::version variable and changed SDATA notation from
+# [SDATA] to |SDATA|.
+#
+# Revision 1.1 1995/04/22 14:40:50 david
+# Initial revision
+#
+########################################################################
+
+use SGMLS::Output;
+
+package SGMLS_PL;
+use SGMLS;
+
+$version = '$Id: sgmlspl.pl,v 1.8 1995/12/03 21:46:31 david Exp $';
+
+#
+# Set up handler defaults.
+#
+$start_document_handler = sub {};
+$end_document_handler = sub {};
+$start_element_handlers = { '' => sub {} };
+$end_element_handlers = { '' => sub {} };
+$cdata_handler = sub { main::output($_[0]); };
+$sdata_handlers = { '' => sub { main::output($_[0]);} };
+$re_handler = sub { main::output("\n"); };
+$pi_handler = sub { '' => sub {} };
+$entity_handlers = { '' => sub {} };
+$start_subdoc_handlers = { '' => sub {} };
+$end_subdoc_handlers = { '' => sub {} };
+$conforming_handler = sub {};
+
+#
+# Main access point: declare handlers for different SGML events.
+#
+# Usage: sgml(event, handler);
+#
+# The event may be one of the following strings, or a special pattern.
+# The generic events are as follow:
+#
+# 'start' The beginning of the document.
+# 'end' The end of the document.
+# 'start_element' The beginning of an element.
+# 'end_element' The end of an element.
+# 'cdata' Regular character data.
+# 'sdata' Special system-specific data.
+# 're' A record-end.
+# 'pi' A processing instruction.
+# 'entity' An external-entity reference.
+# 'start_subdoc' The beginning of a subdocument entity.
+# 'end_subdoc' The end of a subdocument entity.
+# 'conforming' The document is conforming.
+#
+# In addition to these generic events, it is possible to handlers
+# for certain specific, named events, as follow:
+#
+# '<GI>' The beginning of element GI.
+# '</GI>' The end of element GI.
+# '[SDATA]' The system-specific data SDATA.
+# '&ENAME;' A reference to the external entity ENAME.
+# '{ENAME}' The beginning of the subdocument-entity ENAME.
+# '{/ENAME}' The end of the subdocument-entity ENAME.
+#
+#
+# The handler may be a string, which will simply be printed when the
+# event occurs (this is usually useful only for the specific, named
+# events), or a reference to an anonymous subroutine, which will
+# receive two arguments: the event data and the event itself. For
+# example,
+#
+# sgml('<FOO>', "\n\\begin{foo}\n");
+#
+# and
+#
+# sgml('<FOO>', sub { output("\n\\begin{foo}\n"); });
+#
+# will have identical results.
+#
+sub main::sgml {
+ my ($spec,$handler) = (@_);
+ if (ref($handler) ne 'CODE') {
+ $handler =~ s/\\/\\\\/g;
+ $handler =~ s/'/\\'/g;
+ if ($handler eq '') {
+ $handler = sub {};
+ } else {
+ $handler = eval "sub { main::output('$handler'); };";
+ }
+ }
+ SWITCH: {
+ # start-document handler
+ $spec eq 'start' && do {
+ $start_document_handler = $handler;
+ last SWITCH;
+ };
+ # end-document handler
+ $spec eq 'end' && do {
+ $end_document_handler = $handler;
+ last SWITCH;
+ };
+ # start-element handler
+ $spec =~ /^<([^\/].*|)>$/ && do {
+ $start_element_handlers->{$1} = $handler;
+ last SWITCH;
+ };
+ # generic start-element handler
+ $spec eq 'start_element' && do {
+ $start_element_handlers->{''} = $handler;
+ last SWITCH;
+ };
+ # end-element handler
+ $spec =~ /^<\/(.*)>$/ && do {
+ $end_element_handlers->{$1} = $handler;
+ last SWITCH;
+ };
+ # generic end-element handler
+ $spec =~ 'end_element' && do {
+ $end_element_handlers->{''} = $handler;
+ last SWITCH;
+ };
+ # cdata handler
+ $spec eq 'cdata' && do {
+ $cdata_handler = $handler;
+ last SWITCH;
+ };
+ # sdata handler
+ $spec =~ /^\|(.*)\|$/ && do {
+ $sdata_handlers->{$1} = $handler;
+ last SWITCH;
+ };
+ # generic sdata handler
+ $spec eq 'sdata' && do {
+ $sdata_handlers->{''} = $handler;
+ last SWITCH;
+ };
+ # record-end handler
+ $spec eq 're' && do {
+ $re_handler = $handler;
+ last SWITCH;
+ };
+ # processing-instruction handler
+ $spec eq 'pi' && do {
+ $pi_handler = $handler;
+ last SWITCH;
+ };
+ # entity-reference handler
+ $spec =~ /^\&(.*);$/ && do {
+ $entity_handlers->{$1} = $handler;
+ last SWITCH;
+ };
+ # generic entity-reference handler
+ $spec eq 'entity' && do {
+ $entity_handlers->{''} = $handler;
+ last SWITCH;
+ };
+ # start-subdoc handler
+ $spec =~ /^\{([^\/].*|)\}$/ && do {
+ $start_subdoc_handlers->{$1} = $handler;
+ last SWITCH;
+ };
+ # generic start-subdoc handler
+ $spec eq 'start_subdoc' && do {
+ $start_subdoc_handlers->{''} = $handler;
+ last SWITCH;
+ };
+ # end-subdoc handler
+ $spec =~ /^\{\/(.*)\}$/ && do {
+ $end_subdoc_handlers->{$1} = $handler;
+ last SWITCH;
+ };
+ # generic end-subdoc handler
+ $spec eq 'end_subdoc' && do {
+ $end_subdoc_handlers->{''} = $handler;
+ last SWITCH;
+ };
+ # conforming handler
+ $spec eq 'conforming' && do {
+ $conforming_handler = $handler;
+ last SWITCH;
+ };
+
+ die "Bad SGML handler pattern: $spec\n";
+ }
+}
+
+
+#
+# The first argument on the command line is a perl module which will be
+# read here and evaluated in the 'main' package -- everything else will
+# be an argument to it.
+#
+package main;
+
+$ARGV = shift;
+unless ($ARGV eq '' || do $ARGV) {
+ if (!-e $ARGV) {
+ die "FATAL: $ARGV does not exist.\n";
+ } elsif (!-r $ARGV) {
+ die "FATAL: $ARGV exists but is read-protected.\n";
+ } elsif ($@) {
+ die "FATAL: $@\n";
+ }
+}
+
+
+#
+# Do the actual work, using the SGMLS package.
+#
+package SGMLS_PL;
+
+$parse = new SGMLS(main::STDIN); # a new parse object
+
+&{$start_document_handler}(); # run the start handler.
+
+ # run the appropriate handler for each
+ # event
+while ($event = $parse->next_event) {
+ my $type = $event->type;
+ SWITCH: {
+ $type eq 'start_element' && do {
+ &{($start_element_handlers->{$event->data->name}||
+ $start_element_handlers->{''} || sub {})}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'end_element' && do {
+ &{($end_element_handlers->{$event->data->name}||
+ $end_element_handlers->{''} || sub {})}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'cdata' && do {
+ &{$cdata_handler}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'sdata' && do {
+ &{($sdata_handlers->{$event->data}||
+ $sdata_handlers->{''} || sub {})}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 're' && do {
+ &{$re_handler}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'pi' && do {
+ &{$pi_handler}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'entity' && do {
+ &{($entity_handlers->{$event->data->name}||
+ $entity_handlers->{''} || sub {})}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'start_subdoc' && do {
+ &{($start_subdoc_handlers->{$event->data->name}||
+ $start_subdoc_handlers->{''} || sub {})}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'end_subdoc' && do {
+ &{($end_subdoc_handlers->{$event->data->name}||
+ $end_subdoc_handlers->{''} || sub {})}($event->data,$event);
+ last SWITCH;
+ };
+ $type eq 'conforming' && do {
+ &{$conforming_handler}($event->data,$event);
+ last SWITCH;
+ };
+
+ die "Unknown SGML event type: $type\n";
+ }
+}
+
+&{$end_document_handler}(); # run the end handler
diff --git a/info/examples/lwc/ch7/skel.pl b/info/examples/lwc/ch7/skel.pl
new file mode 100644
index 0000000000..f10c1ff3f8
--- /dev/null
+++ b/info/examples/lwc/ch7/skel.pl
@@ -0,0 +1,178 @@
+########################################################################
+# skel.pl: an SGMLSPL script for producing scripts (!!).
+#
+# Copyright (c) 1995 by David Megginson <dmeggins@aix1.uottawa.ca>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# Changes:
+#
+# $Log: skel.pl,v $
+# Revision 1.4 1995/11/15 20:21:07 david
+# Changed "use Output" to "use SGMLS::Output".
+#
+# Revision 1.3 1995/08/24 15:04:38 david
+# Fixed commented-out 're' handler.
+#
+# Revision 1.2 1995/08/12 16:16:42 david
+# Revised version for 1.01 distribution.
+#
+# Revision 1.1 1995/04/23 14:49:35 david
+# Initial revision
+#
+########################################################################
+
+use SGMLS;
+use SGMLS::Output;
+
+$version = '$Id: skel.pl,v 1.4 1995/11/15 20:21:07 david Exp $';
+
+%subdocs = (); # Subdocument entities seen so far.
+%entities = (); # External data entities seen so far.
+%sdata = (); # SDATA strings seen so far.
+%elements = (); # Elements seen so far.
+$pi = 0; # Any processing instructions?
+
+$intro = 0; # Have we printed the banner yet?
+
+$| = 1;
+
+sgml('end_element', ''); # Ignore the ends of elements.
+sgml('end_subdoc', ''); # Ignore the ends of subdocument entities.
+sgml('cdata', ''); # Ignore CDATA.
+sgml('re', ''); # Ignore Record Ends.
+
+ # Note any processing instructions.
+sgml('pi', sub { $pi = 1; });
+
+ # Keep track of all subdocument entities.
+sgml('start_subdoc', sub {
+ my $entity = shift;
+ $entities{$entity->name} = 1;
+});
+ # Keep track of all external data entities.
+sgml('entity', sub {
+ my $entity = shift;
+ $entities{$entity->name} = 1;
+});
+ # Keep track of all SDATA strings
+sgml('sdata', sub {
+ my $sdata = shift;
+ $sdata{$sdata} = 1;
+});
+
+ # Display element handlers as they appear.
+sgml('start_element', sub {
+ my $element = shift;
+ unless ($intro) {
+ $intro = 1;
+ do_intro($element->name);
+ }
+ if (!$elements{$element->name}) {
+ output "# Element: " . $element->name . "\n";
+ output "sgml('<" . $element->name . ">', \"\");\n";
+ output "sgml('</" . $element->name . ">', \"\");\n\n";
+ $elements{$element->name} = 1;
+ }
+});
+
+sgml('end', sub {
+ # generate subdoc handlers
+ my @keys = keys(%subdocs);
+ if ($#keys > 0) {
+ output "#\n# Subdocument Entity Handlers\n#\n\n";
+ foreach (@keys) {
+ output "# Subdocument Entity: $_\n";
+ output "sgml('{" . $_ . "}', \"\");\n";
+ output "sgml('{/" . $_ . "}', \"\");\n\n";
+ }
+ }
+ # generate entity handlers
+ my @keys = keys(%entities);
+ if ($#keys > 0) {
+ output "#\n# External Data Entity Handlers\n#\n\n";
+ foreach (@keys) {
+ output "sgml('&" . $_ . ";', \"\");\n";
+ }
+ }
+ # generate sdata handlers
+ my @keys = keys(%sdata);
+ if ($#keys > 0) {
+ output "#\n# SDATA Handlers\n#\n\n";
+ foreach (@keys) {
+ output "sgml('|" . $_ . "|', \"\");\n";
+ }
+ }
+
+ if ($pi) {
+ output "#\n# Processing-Instruction Handler\n#\n";
+ output "sgml('pi', sub {});\n\n";
+ }
+
+ output <<END;
+#
+# Default handlers (uncomment these if needed). Right now, these are set
+# up to gag on any unrecognised elements, sdata, processing-instructions,
+# or entities.
+#
+# sgml('start_element',sub { die "Unknown element: " . \$_[0]->name; });
+# sgml('end_element','');
+# sgml('cdata',sub { output \$_[0]; });
+# sgml('sdata',sub { die "Unknown SDATA: " . \$_[0]; });
+# sgml('re',"\\n");
+# sgml('pi',sub { die "Unknown processing instruction: " . \$_[0]; });
+# sgml('entity',sub { die "Unknown external entity: " . \$_[0]->name; });
+# sgml('start_subdoc',sub { die "Unknown subdoc entity: " . \$_[0]->name; });
+# sgml('end_subdoc','');
+# sgml('conforming','');
+
+1;
+END
+});
+
+
+
+ # Function to print the banner.
+sub do_intro {
+ my $doctype = shift;
+ output <<END;
+########################################################################
+# SGMLSPL script produced automatically by the script sgmlspl.pl
+#
+# Document Type: $doctype
+# Edited by:
+########################################################################
+
+use SGMLS; # Use the SGMLS package.
+use SGMLS::Output; # Use stack-based output.
+
+#
+# Document Handlers.
+#
+sgml('start', sub {});
+sgml('end', sub {});
+
+#
+# Element Handlers.
+#
+
+END
+}
+
+1;
+
+
+
diff --git a/info/examples/lwc/ch7/style-sheet.dtd b/info/examples/lwc/ch7/style-sheet.dtd
new file mode 100644
index 0000000000..0ee4e674d3
--- /dev/null
+++ b/info/examples/lwc/ch7/style-sheet.dtd
@@ -0,0 +1,41 @@
+<!-- A DTD for DSSSL Style Sheets. The public identifier for this is
+
+ "-//James Clark//DTD DSSSL Style Sheet//EN"
+-->
+
+<!element style-sheet o o (style-specification,
+ (external-specification|style-specification)*)>
+<!element style-specification o o (style-specification-body)>
+<!attlist style-specification
+ id id #implied
+ use idrefs #implied
+>
+<!element style-specification-body o o (#pcdata)>
+<!attlist style-specification-body
+ content entity #conref
+>
+<!element external-specification - o empty>
+<!attlist external-specification
+ id id #required
+ document entity #required
+ specid name #implied
+>
+<?IS10744 ArcBase DSSSL>
+<!NOTATION DSSSL PUBLIC "ISO/IEC 10179:1996//NOTATION
+ DSSSL Architecture Definition Document//EN"
+ -- A document architecture conforming to the
+ Architectural Form Definition Requirements of
+ ISO/IEC 10744. --
+>
+
+<!ATTLIST #NOTATION DSSSL
+ -- Support attributes for all architectures --
+ ArcQuant CDATA #FIXED "NAMELEN 64"
+ ArcDTD CDATA #FIXED "%DSSSLDTD"
+ ArcDocF NAME #FIXED dsssl-specification
+ ArcDataF NAME #FIXED dsssl-specification
+>
+
+<!ENTITY % DSSSLDTD PUBLIC
+ "ISO/IEC 10179:1996//DTD DSSSL Architecture//EN"
+>
diff --git a/info/examples/lwc/ch7/templatest.xml b/info/examples/lwc/ch7/templatest.xml
new file mode 100644
index 0000000000..be664cb09e
--- /dev/null
+++ b/info/examples/lwc/ch7/templatest.xml
@@ -0,0 +1,3 @@
+<invitation>
+<to>Anna, Bernard, Didier, Johanna</to>
+</invitation>
diff --git a/info/examples/lwc/ch7/templatest.xsl b/info/examples/lwc/ch7/templatest.xsl
new file mode 100644
index 0000000000..c1bfa378b6
--- /dev/null
+++ b/info/examples/lwc/ch7/templatest.xsl
@@ -0,0 +1,41 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ xmlns:fo="http://www.w3.org/XSL/Format/1.0"
+ result-ns="fo"
+ default-space="">
+<xsl:template name="listitem">
+ <xsl:param-variable name="labeltext">labeltext</xsl:param-variable>
+ <xsl:param-variable name="itemid">itemid</xsl:param-variable>
+ <xsl:param-variable name="itemtext">itemtext</xsl:param-variable>
+ <fo:list-item id="{$itemid}">
+ <fo:list-item-label font-style="italic">
+ $labeltext<xsl:text>:</xsl:text>
+ </fo:list-item-label>
+ <fo:list-item-body>
+ <xsl:value-of select="$itemtext"/>
+ </fo:list-item-body>
+ </fo:list-item>
+</xsl:template>
+
+<xsl:template match='/'>
+ <fo:page-sequence>
+ <xsl:apply-templates/>
+ </fo:page-sequence>
+</xsl:template>
+
+<xsl:template match="invitation">
+<fo:list-block>
+ <xsl:call-template name="listitem">
+ <xsl:param name="labeltext">To</xsl:param>
+ <xsl:param name="itemid">listto</xsl:param>
+ <xsl:param name="itemtext">to</xsl:param>
+ </xsl:call-template>
+</fo:list-block>
+</xsl:template>
+
+</xsl:stylesheet>
+
+
+
+
+
diff --git a/info/examples/lwc/ch7/templatestnok.xsl b/info/examples/lwc/ch7/templatestnok.xsl
new file mode 100644
index 0000000000..c1bfa378b6
--- /dev/null
+++ b/info/examples/lwc/ch7/templatestnok.xsl
@@ -0,0 +1,41 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ xmlns:fo="http://www.w3.org/XSL/Format/1.0"
+ result-ns="fo"
+ default-space="">
+<xsl:template name="listitem">
+ <xsl:param-variable name="labeltext">labeltext</xsl:param-variable>
+ <xsl:param-variable name="itemid">itemid</xsl:param-variable>
+ <xsl:param-variable name="itemtext">itemtext</xsl:param-variable>
+ <fo:list-item id="{$itemid}">
+ <fo:list-item-label font-style="italic">
+ $labeltext<xsl:text>:</xsl:text>
+ </fo:list-item-label>
+ <fo:list-item-body>
+ <xsl:value-of select="$itemtext"/>
+ </fo:list-item-body>
+ </fo:list-item>
+</xsl:template>
+
+<xsl:template match='/'>
+ <fo:page-sequence>
+ <xsl:apply-templates/>
+ </fo:page-sequence>
+</xsl:template>
+
+<xsl:template match="invitation">
+<fo:list-block>
+ <xsl:call-template name="listitem">
+ <xsl:param name="labeltext">To</xsl:param>
+ <xsl:param name="itemid">listto</xsl:param>
+ <xsl:param name="itemtext">to</xsl:param>
+ </xsl:call-template>
+</fo:list-block>
+</xsl:template>
+
+</xsl:stylesheet>
+
+
+
+
+
diff --git a/info/examples/lwc/ch7/templatestok.xsl b/info/examples/lwc/ch7/templatestok.xsl
new file mode 100644
index 0000000000..73a4e2d3fd
--- /dev/null
+++ b/info/examples/lwc/ch7/templatestok.xsl
@@ -0,0 +1,31 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ xmlns:fo="http://www.w3.org/XSL/Format/1.0"
+ result-ns="fo"
+ default-space="">
+
+<xsl:template match='/'>
+ <fo:page-sequence>
+ <xsl:apply-templates/>
+ </fo:page-sequence>
+</xsl:template>
+
+<xsl:template match="invitation">
+<fo:list-block>
+ <fo:list-item id="listto">
+ <fo:list-item-label font-style="italic">
+ <xsl:text>To:</xsl:text>
+ </fo:list-item-label>
+ <fo:list-item-body>
+ <xsl:value-of select="to"/>
+ </fo:list-item-body>
+ </fo:list-item>
+</fo:list-block>
+</xsl:template>
+
+</xsl:stylesheet>
+
+
+
+
+
diff --git a/info/examples/lwc/ch7/test-SGMLS.pl b/info/examples/lwc/ch7/test-SGMLS.pl
new file mode 100644
index 0000000000..f18f972832
--- /dev/null
+++ b/info/examples/lwc/ch7/test-SGMLS.pl
@@ -0,0 +1,13 @@
+use SGMLS;
+
+$\ = "\n";
+
+$parse = new SGMLS(STDIN);
+
+while ($event = $parse->next_event) {
+ print "Event type: " . $event->type;
+ print "Data: " . $event->data;
+ print "File: " . $event->file || "[unavailable]";
+ print "Line: " . $event->line || "[unavailable]";
+ print "";
+}
diff --git a/info/examples/lwc/ch7/writefile.xsl b/info/examples/lwc/ch7/writefile.xsl
new file mode 100644
index 0000000000..bdf60c8e00
--- /dev/null
+++ b/info/examples/lwc/ch7/writefile.xsl
@@ -0,0 +1,8 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" default-space="strip">
+ <xsl:template match="file">
+ <xsl:invoke classid="java:com.jclark.xsl.sax.TextFileOutputFilter">
+ <xsl:arg name="file" value="{@filename}"/>
+ <xsl:apply-templates/>
+ </xsl:invoke>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/info/examples/lwc/ch7/writefiles.xml b/info/examples/lwc/ch7/writefiles.xml
new file mode 100644
index 0000000000..0f1db9648a
--- /dev/null
+++ b/info/examples/lwc/ch7/writefiles.xml
@@ -0,0 +1,9 @@
+<outputfiles>
+<file filename="filea.out">
+10 &lt; 20
+</file>
+<file filename="fileb.out">
+43 &gt; 34
+An ampersand character: &amp;.
+</file>
+</outputfiles>
diff --git a/info/examples/lwc/ch7/wrong.xml b/info/examples/lwc/ch7/wrong.xml
new file mode 100644
index 0000000000..4f3827b7ad
--- /dev/null
+++ b/info/examples/lwc/ch7/wrong.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!DOCTYPE wrong [
+<!ELEMENT wrong (par*)>
+<!ELEMENT par (#PCDATA|emph)*>
+<!ELEMENT emph (#PCDATA)*>
+]>
+<wrong>
+<par>This part has wrong entity syntax &lt;par&gt.</par>
+<emph>Emph text outside scope.</emph>
+<par>Here comes another error <par>a second level
+paragraph</par>.</par>
+<par>A wrongly nested <emph>construct</par></emph>.
+Some more text outside valid scope
+<par>Reserved characters "&" "<" ">" ";" .</par>
+</wrong>
diff --git a/info/examples/lwc/ch7/xml.dcl b/info/examples/lwc/ch7/xml.dcl
new file mode 100644
index 0000000000..db70162541
--- /dev/null
+++ b/info/examples/lwc/ch7/xml.dcl
@@ -0,0 +1,179 @@
+<!SGML -- SGML Declaration for valid XML documents --
+ "ISO 8879:1986 (WWW)"
+
+ CHARSET
+ BASESET
+ "ISO Registration Number 176//CHARSET
+ ISO/IEC 10646-1:1993 UCS-4 with implementation
+ level 3//ESC 2/5 2/15 4/6"
+ DESCSET
+ 0 9 UNUSED
+ 9 2 9
+ 11 2 UNUSED
+ 13 1 13
+ 14 18 UNUSED
+ 32 95 32
+ 127 1 UNUSED
+ 128 32 UNUSED
+ -- use this instead of the official declaration because SP only
+ supports 16-bit characters --
+ 160 65374 160
+ 65534 2 UNUSED
+ -- 55296 2048 UNUSED
+ 57344 8190 57344
+ 65534 2 UNUSED
+ 65536 1048576 65536 --
+ CAPACITY NONE
+
+ SCOPE DOCUMENT
+
+ SYNTAX
+ SHUNCHAR NONE
+ BASESET "ISO Registration Number 176//CHARSET
+ ISO/IEC 10646-1:1993 UCS-4 with implementation
+ level 3//ESC 2/5 2/15 4/6"
+ DESCSET
+ 0 1114112 0
+ FUNCTION
+ RE 13
+ RS 10
+ SPACE 32
+ TAB SEPCHAR 9
+
+ NAMING
+ LCNMSTRT ""
+ UCNMSTRT ""
+ NAMESTRT
+ 58 95 192-214 216-246 248-305 308-318 321-328
+ 330-382 384-451 461-496 500-501 506-535 592-680
+ 699-705 902 904-906 908 910-929 931-974 976-982
+ 986 988 990 992 994-1011 1025-1036 1038-1103
+ 1105-1116 1118-1153 1168-1220 1223-1224
+ 1227-1228 1232-1259 1262-1269 1272-1273
+ 1329-1366 1369 1377-1414 1488-1514 1520-1522
+ 1569-1594 1601-1610 1649-1719 1722-1726
+ 1728-1742 1744-1747 1749 1765-1766 2309-2361
+ 2365 2392-2401 2437-2444 2447-2448 2451-2472
+ 2474-2480 2482 2486-2489 2524-2525 2527-2529
+ 2544-2545 2565-2570 2575-2576 2579-2600
+ 2602-2608 2610-2611 2613-2614 2616-2617
+ 2649-2652 2654 2674-2676 2693-2699 2701
+ 2703-2705 2707-2728 2730-2736 2738-2739
+ 2741-2745 2749 2784 2821-2828 2831-2832
+ 2835-2856 2858-2864 2866-2867 2870-2873 2877
+ 2908-2909 2911-2913 2949-2954 2958-2960
+ 2962-2965 2969-2970 2972 2974-2975 2979-2980
+ 2984-2986 2990-2997 2999-3001 3077-3084
+ 3086-3088 3090-3112 3114-3123 3125-3129
+ 3168-3169 3205-3212 3214-3216 3218-3240
+ 3242-3251 3253-3257 3294 3296-3297 3333-3340
+ 3342-3344 3346-3368 3370-3385 3424-3425
+ 3585-3630 3632 3634-3635 3648-3653 3713-3714
+ 3716 3719-3720 3722 3725 3732-3735 3737-3743
+ 3745-3747 3749 3751 3754-3755 3757-3758 3760
+ 3762-3763 3773 3776-3780 3904-3911 3913-3945
+ 4256-4293 4304-4342 4352 4354-4355 4357-4359
+ 4361 4363-4364 4366-4370 4412 4414 4416 4428
+ 4430 4432 4436-4437 4441 4447-4449 4451 4453
+ 4455 4457 4461-4462 4466-4467 4469 4510 4520
+ 4523 4526-4527 4535-4536 4538 4540-4546 4587
+ 4592 4601 7680-7835 7840-7929 7936-7957
+ 7960-7965 7968-8005 8008-8013 8016-8023 8025
+ 8027 8029 8031-8061 8064-8116 8118-8124 8126
+ 8130-8132 8134-8140 8144-8147 8150-8155
+ 8160-8172 8178-8180 8182-8188 8486 8490-8491
+ 8494 8576-8578 12295 12321-12329 12353-12436
+ 12449-12538 12549-12588 19968-40869 44032-55203
+
+ LCNMCHAR ""
+ UCNMCHAR ""
+ NAMECHAR
+ 45-46 183 720-721 768-837 864-865 903 1155-1158
+ 1425-1441 1443-1465 1467-1469 1471 1473-1474
+ 1476 1600 1611-1618 1632-1641 1648 1750-1764
+ 1767-1768 1770-1773 1776-1785 2305-2307 2364
+ 2366-2381 2385-2388 2402-2403 2406-2415
+ 2433-2435 2492 2494-2500 2503-2504 2507-2509
+ 2519 2530-2531 2534-2543 2562 2620 2622-2626
+ 2631-2632 2635-2637 2662-2673 2689-2691 2748
+ 2750-2757 2759-2761 2763-2765 2790-2799
+ 2817-2819 2876 2878-2883 2887-2888 2891-2893
+ 2902-2903 2918-2927 2946-2947 3006-3010
+ 3014-3016 3018-3021 3031 3047-3055 3073-3075
+ 3134-3140 3142-3144 3146-3149 3157-3158
+ 3174-3183 3202-3203 3262-3268 3270-3272
+ 3274-3277 3285-3286 3302-3311 3330-3331
+ 3390-3395 3398-3400 3402-3405 3415 3430-3439
+ 3633 3636-3642 3654-3662 3664-3673 3761
+ 3764-3769 3771-3772 3782 3784-3789 3792-3801
+ 3864-3865 3872-3881 3893 3895 3897 3902-3903
+ 3953-3972 3974-3979 3984-3989 3991 3993-4013
+ 4017-4023 4025 8400-8412 8417 12293 12330-12335
+ 12337-12341 12441-12442 12445-12446 12540-12542
+
+ NAMECASE
+ GENERAL NO
+ ENTITY NO
+
+ DELIM
+ GENERAL SGMLREF
+ HCRO "&#38;#x" -- 38 is the number for ampersand --
+ NESTC "/"
+ NET ">"
+ PIC "?>"
+ SHORTREF NONE
+
+ NAMES
+ SGMLREF
+
+ QUANTITY NONE
+
+ ENTITIES
+ "amp" 38
+ "lt" 60
+ "gt" 62
+ "quot" 34
+ "apos" 39
+
+ FEATURES
+ MINIMIZE
+ DATATAG NO
+ OMITTAG NO
+ RANK NO
+ SHORTTAG
+ STARTTAG
+ EMPTY NO
+ UNCLOSED NO
+ NETENABL IMMEDNET
+ ENDTAG
+ EMPTY NO
+ UNCLOSED NO
+ ATTRIB
+ DEFAULT YES
+ OMITNAME NO
+ VALUE NO
+ EMPTYNRM YES
+ IMPLYDEF
+ ATTLIST NO
+ DOCTYPE NO
+ ELEMENT NO
+ ENTITY NO
+ NOTATION NO
+ LINK
+ SIMPLE NO
+ IMPLICIT NO
+ EXPLICIT NO
+ OTHER
+ CONCUR NO
+ SUBDOC NO
+ FORMAL NO
+ URN NO
+ KEEPRSRE YES
+ VALIDITY TYPE
+ ENTITIES
+ REF ANY
+ INTEGRAL YES
+ APPINFO NONE
+ SEEALSO "ISO 8879:1986//NOTATION
+ Extensible Markup Language (XML) 1.0//EN"
+>
diff --git a/info/examples/lwc/ch7/xsl.xml b/info/examples/lwc/ch7/xsl.xml
new file mode 100644
index 0000000000..6cbab1f894
--- /dev/null
+++ b/info/examples/lwc/ch7/xsl.xml
@@ -0,0 +1,3838 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet href="stylesheet/xml.dsl" type="text/dsssl"?>
+<!-- $Id: xsl.xml 1.223 1998/12/02 10:12:01 jjc Exp $ -->
+<!DOCTYPE spec SYSTEM "xslspec.dtd" [
+<!ENTITY XMLRec "http://www.w3.org/TR/REC-xml">
+<!ENTITY XMLNames "http://www.w3.org/TR/WD-xml-names">
+<!ENTITY year "1998">
+<!ENTITY month "December">
+<!ENTITY day "2">
+<!ENTITY MMDD "1202">
+<!ENTITY fo SYSTEM "fo.xml">
+<!ENTITY D "DSSSL:">
+<!ENTITY C "CSS:">
+]>
+<spec>
+<header>
+<title>Extensible Stylesheet Language (XSL)</title>
+<version>Version 1.0</version>
+<w3c-designation>WD-xsl-&year;&MMDD;</w3c-designation>
+<w3c-doctype>World Wide Web Consortium Working Draft</w3c-doctype>
+<pubdate><day>&day;</day><month>&month;</month><year>&year;</year></pubdate>
+<publoc>
+<loc href="http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;"
+ >http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;</loc>
+<loc href="http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;.xml"
+ >http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;.xml</loc>
+<loc href="http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;.html"
+ >http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;.html</loc>
+<loc href="http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;.pdf"
+ >http://www.w3.org/TR/&year;/WD-xsl-&year;&MMDD;.pdf</loc>
+</publoc>
+<latestloc>
+<loc href="http://www.w3.org/TR/WD-xsl"
+ >http://www.w3.org/TR/WD-xsl</loc>
+</latestloc>
+<prevlocs>
+<loc href="http://www.w3.org/TR/1998/WD-xsl-19980818"
+ >http://www.w3.org/TR/1998/WD-xsl-19980818</loc>
+</prevlocs>
+<authlist>
+<author part="Tree Construction">
+<name>James Clark</name>
+<email href="mailto:jjc@jclark.com">jjc@jclark.com</email>
+</author>
+<author part="Formatting Objects">
+<name>Stephen Deach</name>
+<affiliation>Adobe</affiliation>
+<email href="mailto:sdeach@adobe.com">sdeach@adobe.com</email>
+</author>
+</authlist>
+
+<status>
+
+<p>This is a W3C Working Draft for review by W3C members and other
+interested parties. This adds additional functionality to what was
+described in the the previous draft, however the basic of the previous
+draft remains unchanged. It is a draft document and may be updated,
+replaced, or obsoleted by other documents at any time. The XSL
+Working Group will not allow early implementation to constrain its
+ability to make changes to this specification prior to final release.
+It is inappropriate to use W3C Working Drafts as reference material or
+to cite them as other than <quote>work in progress</quote>. A list of
+current W3C working drafts can be found at <loc
+href="http://www.w3.org/TR">http://www.w3.org/TR</loc>.</p>
+
+<p>Comments may be sent to <loc
+href="mailto:xsl-editors@w3.org">xsl-editors@w3.org</loc>. Public
+discussion of XSL takes place on the <loc
+href="http://www.mulberrytech.com/xsl/xsl-list/index.html">XSL-List</loc>
+mailing list.</p>
+
+</status>
+
+<abstract>
+
+<p>XSL is a language for expressing stylesheets. It consists of two
+parts:</p>
+
+<olist>
+
+<item><p>a language for transforming XML documents, and</p></item>
+
+<item><p>an XML vocabulary for specifying formatting
+semantics.</p></item>
+
+</olist>
+
+<p>An XSL stylesheet specifies the presentation of a class of XML
+documents by describing how an instance of the class is transformed
+into an XML document that uses the formatting vocabulary.</p>
+
+</abstract>
+
+<langusage>
+<language id="EN">English</language>
+<language id="ebnf">EBNF</language>
+</langusage>
+<revisiondesc>
+<slist>
+<sitem>See RCS log for revision history.</sitem>
+</slist>
+</revisiondesc>
+</header>
+<body>
+<div1>
+<head>Overview</head>
+
+<p>XSL is a language for expressing stylesheets. Each stylesheet
+describes rules for presenting a class of XML source documents. There
+are two parts to the presentation process. First, the result tree is
+constructed from the source tree. Second, the result tree is
+interpreted to produce formatted output on a display, on paper, in
+speech or onto other media.</p>
+
+<p>The first part, constructing the result tree, is achieved by
+associating patterns with templates. A pattern is matched against
+elements in the source tree. A template is instantiated to create
+part of the result tree. The result tree is separate from the source
+tree. The structure of the result tree can be completely different
+from the structure of the source tree. In constructing the result
+tree, the source tree can be filtered and reordered, and arbitrary
+structure can be added.</p>
+
+<p>The second part, formatting, is achieved by using the formatting
+vocabulary specified in this document to construct the result tree.
+Formally, this vocabulary is an XML namespace. Each element type in the
+vocabulary corresponds to a formatting object class. A formatting
+object class represents a particular kind of formatting behavior. For
+example, the block formatting object class represents the breaking of
+the content of a paragraph into lines. Each attribute in the
+vocabulary corresponds to a formatting property. A formatting object
+class has a specific set of formatting properties which provide finer
+control over the behavior of the formatting object class; for example,
+controlling indenting of lines, spacing between lines, and spacing
+before and after the collection of lines. A formatting object can
+have content, and its formatting behavior is applied to its
+content.</p>
+
+<p>XSL does not require result trees to use the formatting vocabulary
+and thus can be used for general XML transformations. For example,
+XSL can be used to transform XML to <quote>well-formed</quote> HTML,
+that is, XML that uses the element types and attributes defined by
+HTML.</p>
+
+<p>When the result tree uses the formatting vocabulary, a conforming
+XSL implementation must be able to interpret the result tree according
+to the semantics of the formatting vocabulary as defined in this
+document; it may also be able to externalize the result tree as XML,
+but it is not required to be able to do so.</p>
+
+<p>This document does not specify how a stylesheet is associated with
+an XML document. It is recommended that XSL processors support the
+mechanism described in <bibref ref="XMLSTYLE"/>.</p>
+
+</div1>
+
+<div1>
+<head>Tree Construction</head>
+
+<div2>
+<head>Overview</head>
+
+<p>A stylesheet contains a set of template rules. A
+template rule has two parts: a pattern which is matched against nodes
+in the source tree and a template which can be instantiated
+to form part of the result tree. This allows a stylesheet to be applicable to
+a wide class of documents that have similar source tree
+structures.</p>
+
+<p>A template is instantiated for a particular source element
+to create part of the result tree. A template can contain elements
+that specify literal result element structure. A template can also
+contain elements that are instructions for creating result tree
+fragments. When a template is instantiated, each instruction is
+executed and replaced by the result tree fragment that it creates.
+Instructions can select and process descendant elements. Processing a
+descendant element creates a result tree fragment by finding the
+applicable template rule and instantiating its template. Note
+that elements are only processed when they have been selected by the
+execution of an instruction. The result tree is constructed by
+finding the template rule for the root node and instantiating
+its template.</p>
+
+<p>In the process of finding the applicable template rule, more
+than one template rule may have a pattern that matches a given
+element. However, only one template rule will be applied. The
+method for deciding which template rule to apply is described
+in <specref ref="conflict"/>.</p>
+
+<p>XSL uses XML namespaces <bibref ref="XMLNAMES"/> to distinguish
+elements that are instructions to the XSL processor from elements that
+specify literal result tree structure. Instruction elements all
+belong to the XSL namespace. The examples in this document use a
+prefix of <code>xsl:</code> for elements in the XSL namespace.</p>
+
+<p>An XSL stylesheet contains an <code>xsl:stylesheet</code> document
+element. This element may contain <code>xsl:template</code> elements
+specifying template rules, which will be described later in
+this document.</p>
+
+<p>The following is an example of a simple XSL stylesheet that
+constructs a result tree for a sequence of <code>para</code> elements.
+The <code>result-ns="fo"</code> attribute indicates that a tree using
+the formatting object vocabulary is being constructed. The rule for
+the root node specifies the use of a page sequence formatted with any
+font with serifs. The <code>para</code> elements become
+<code>block</code> formatting objects which are set in 10 point type
+with a 12 point space before each block.</p>
+
+<eg><![CDATA[<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/TR/WD-xsl"
+ xmlns:fo="http://www.w3.org/TR/WD-xsl/FO"
+ result-ns="fo">
+ <xsl:template match="/">
+ <fo:page-sequence font-family="serif">
+ <xsl:apply-templates/>
+ </fo:page-sequence>
+ </xsl:template>
+
+ <xsl:template match="para">
+ <fo:block font-size="10pt" space-before="12pt">
+ <xsl:apply-templates/>
+ </fo:block>
+ </xsl:template>
+</xsl:stylesheet>]]></eg>
+
+<p>The <code>xsl:stylesheet</code> element can also contain elements
+importing other XSL stylesheets, elements defining macros, elements
+defining global constants, and elements identifying source attributes
+as individual element identifiers.</p>
+
+</div2>
+
+<div2>
+<head>Stylesheet Structure</head>
+
+<p>A stylesheet is represented by an <code>xsl:stylesheet</code>
+element in an XML document.</p>
+
+<p>XSL processors must use the XML namespaces mechanism <bibref
+ref="XMLNAMES"/> for both source documents and stylesheets. All XSL
+defined elements, that is those specified in this document with a
+prefix of <code>xsl:</code>, will only be recognized by the XSL
+processor if they belong to a namespace with the URI
+<code>http://www.w3.org/TR/WD-xsl</code>; XSL defined elements are
+recognized only in the stylesheet not in the source document.</p>
+
+<issue id="issue-versioning"><p>Should there be some way for a
+stylesheet to indicate which version of XSL it conforms to? Can this
+be done through the URI of the XSL namespace?</p></issue>
+
+<p>The <code>xsl:stylesheet</code> element has an optional
+<code>result-ns</code> attribute; the value must be a namespace
+prefix. If this attribute is specified, all result elements must
+belong to the namespace identified by this prefix (the <term>result
+namespace</term>). If there is a namespace declared as the default
+namespace, then an empty string may be used as the value to specify
+that the default namespace is the result namespace. If the
+<code>result-ns</code> attribute specifies the XSL Formatting Objects
+namespace, then in addition to constructing the result XML tree, the
+XSL processor must interpret it according to the semantics defined in
+this document. The XSL Formatting Objects namespace has the URI
+<code>http://www.w3.org/TR/WD-xsl/FO</code>. The examples in this
+document use the <code>fo:</code> prefix for this namespace.</p>
+
+<note><p>If an implementation wishes to use something in the result
+tree or stylesheet to control the output of a non-XML representation
+of the result tree, it should use the result namespace. In
+particular, if it wishes to make use of something in the result tree
+or stylesheet to indicate that the result tree should be output as
+HTML that conforms to the HTML 4.0 Recommendation rather than as XML,
+it should use a result namespace of
+<code>http://www.w3.org/TR/REC-html40</code>; for example,</p>
+
+<eg><![CDATA[
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/TR/WD-xsl"
+ xmlns="http://www.w3.org/TR/REC-html40"
+ result-ns="">
+
+<xsl:template match="/">
+ <html>
+ <xsl:apply-templates/>
+ </html>
+</xsl:template>
+
+...
+
+</xsl:stylesheet>]]></eg>
+</note>
+
+<p>The <code>xsl:stylesheet</code> element may contain the following types
+of elements:</p>
+<olist>
+<item><p><code>xsl:import</code></p></item>
+<item><p><code>xsl:include</code></p></item>
+<item><p><code>xsl:id</code></p></item>
+<item><p><code>xsl:strip-space</code></p></item>
+<item><p><code>xsl:preserve-space</code></p></item>
+<item><p><code>xsl:macro</code></p></item>
+<item><p><code>xsl:attribute-set</code></p></item>
+<item><p><code>xsl:constant</code></p></item>
+<item><p><code>xsl:template</code></p></item>
+</olist>
+
+<p>This example shows the structure of a stylesheet. Ellipses
+(<code>...</code>) indicate where attribute values or content have
+been omitted.
+Although this example shows one of each type of allowed element,
+stylesheets may contain zero or more of each of these elements.</p>
+
+<eg><![CDATA[<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
+ <xsl:import href="..."/>
+
+ <xsl:include href="..."/>
+
+ <xsl:id attribute="..."/>
+
+ <xsl:strip-space element="..."/>
+
+ <xsl:preserve-space element="..."/>
+
+ <xsl:macro name="...">
+ ...
+ </xsl:macro>
+
+ <xsl:attribute-set name="...">
+ ...
+ </xsl:attribute-set>
+
+ <xsl:constant name="..." value="..."/>
+
+ <xsl:template match="...">
+ ...
+ </xsl:template>
+</xsl:stylesheet>]]></eg>
+
+<p>The order in which the children of the <code>xsl:stylesheet</code>
+element occur is not significant except for <code>xsl:import</code>
+elements and for error recovery. Users are free to order the elements
+as they prefer, and stylesheet creation tools need not provide control
+over the order in which the elements occur.</p>
+
+<issue id="issue-media-rule"><p>Should we provide the functionality
+of CSS's <code>@media</code> rule and if so how?</p></issue>
+
+</div2>
+
+<div2>
+<head>Processing Model</head>
+
+<ednote><edtext>This needs expanding and polishing.</edtext></ednote>
+
+<p>A node is processed to create a result tree fragment. The
+result tree is constructed by processing the root node. A node is
+processed by finding all the template rules with patterns that
+match the node, and choosing the best amongst them. The chosen rule's
+template is then instantiated for the node. <termdef
+id="dt-current-node" term="Current Node">During the instantiation of
+a template, the node for which the template is being
+instantiated is called the current node.</termdef> A template
+typically contains instructions that select an additional sequence of
+source nodes for processing. A sequence of source nodes is processed
+by appending the result tree structure created by processing each of
+the members of the sequence in order. The process of matching,
+instantiation and selection is continued recursively until no new
+source nodes are selected for processing.</p>
+
+<p>Implementations are free to process the source document in any way
+that produces the same result as if it were processed using this
+processing model.</p>
+
+</div2>
+
+<div2 id="data-model">
+<head>Data Model</head>
+
+<p>XSL operates on an XML document, whether a stylesheet or a source
+document, as a tree. Any two stylesheets or source documents that
+have the same tree will be processed the same by XSL. The XML
+document resulting from the tree construction process is also a tree.
+This section describes how XSL models an XML document as a tree. This
+model is conceptual only and does not mandate any particular
+implementation.</p>
+
+<p>XML documents operated on by XSL must conform to the XML namespaces
+specification <bibref ref="XMLNAMES"/>.</p>
+
+<p>The tree contains nodes. There are seven kinds of node:</p>
+
+<ulist>
+
+<item><p>root nodes</p></item>
+
+<item><p>element nodes</p></item>
+
+<item><p>text nodes</p></item>
+
+<item><p>attribute nodes</p></item>
+
+<item><p>namespace nodes</p></item>
+
+<item><p>processing instruction nodes</p></item>
+
+<item><p>comment nodes</p></item>
+
+</ulist>
+
+<p>Neither processing instruction nodes nor comment nodes are included
+in the tree for the stylesheet.</p>
+
+<p>For every type of node there is a way of determing a string
+<term>value</term> for a node of that type. For some types of node,
+the value is part of the node; for other types of node, the value is
+computed from the value of descendant nodes.</p>
+
+<issue id="issue-data-entity"><p>Should XSL provide support for
+external data entities and notations?</p></issue>
+
+<div3 id="root-node">
+<head>Root Node</head>
+
+<p>The root node is the root of the tree. It does not occur anywhere
+else in the tree. It has a single child which is the element node for
+the document element of the document.</p>
+
+<p>The <term>value</term> of the root node is the value of the
+document element.</p>
+
+</div3>
+
+<div3 id="element-nodes">
+<head>Element Nodes</head>
+
+<p>There is an element node for every element in the document. An
+element has an expanded name consisting of a local name and a possibly
+null URI (see <bibref ref="XMLNAMES"/>); the URI will be null if the
+element type name has no prefix and there is no default namespace in
+scope.</p>
+
+<p>The children of an element node are the element nodes and
+characters for its content. Entity references to both internal and
+external entities are expanded. Character references are
+resolved.</p>
+
+<p><termdef id="dt-descendants" term="Descendants">The
+<term>descendants</term> of an element node are the character
+children, the element node children, and the descendants of the
+element node children.</termdef></p>
+
+<p>The <term>value</term> of an element node is the string that
+results from concatenating all characters that are <termref
+def="dt-descendants">descendants</termref> of the element node in the
+order in which they occur in the document.</p>
+
+<p><termdef id="dt-document-order" term="Document Order">The set of
+all element nodes in a document can be ordered according to the order
+of the start-tags of the elements in the document; this is known as
+<term>document order</term>.</termdef></p>
+
+<div4 id="unique-id">
+<head>Unique IDs</head>
+
+<p>An element object may have a unique identifier (ID). This is the
+value of the attribute which is declared in the DTD as type
+<code>ID</code>. Since XSL must also work with XML documents that do
+not have a DTD, stylesheets may specify which attributes in the source
+document should be treated as IDs. The <code>xsl:id</code> element
+has a required <code>attribute</code> attribute, which gives the name
+of an attribute in the source document that should be treated as
+specifying the element's ID. A stylesheet may contain more than one
+<code>xsl:id</code> element, for cases where the source document uses
+several attributes as IDs. An <code>xsl:id</code> element also has an
+optional <code>element</code> attribute which specifies the name of an
+element type; when the <code>element</code> attribute is specified,
+then the <code>xsl:id</code> element specifies that the
+<code>attribute</code> attribute of <code>element</code> elements are
+treated as IDs. <code>xsl:id</code> elements may only occur in the
+stylesheet body (not within a rule). The following causes XSL to
+treat all <code>name</code> attributes in the source document as
+IDs.</p>
+
+<eg><![CDATA[<xsl:id attribute="name"/>]]></eg>
+
+<p>It is an error if, as a consequence of the use of
+<code>xsl:id</code>, there is more than one element with the same ID
+in the source tree. An XSL processor may signal the error; if it does
+not signal the error, it must recover by treating only the first (in
+<termref def="dt-document-order">document order</termref>) of the
+elements as having that ID.</p>
+
+<issue id="unique-id-content"><p>Should it be possible for a unique id
+to be specified in the content of an element instead of in an
+attribute?</p></issue>
+
+</div4>
+
+<div4 id="base-uri">
+
+<head>Base URI</head>
+
+<p>An element node also has an associated URI called its base URI
+which is used for resolving attribute values that represent relative
+URIs into absolute URIs. If an element occurs in an external entity,
+the base URI of that element is the URI of the external entity.
+Otherwise the base URI is the base URI of the document.</p>
+
+</div4>
+
+</div3>
+
+<div3 id="attribute-nodes">
+<head>Attribute Nodes</head>
+
+<p>Each element node has an associated set of attribute nodes. A
+defaulted attribute is treated the same as a specified attribute. If
+an attribute was declared for the element type, but the default was
+declared as <code>#IMPLIED</code>, and the attribute was not specified
+on the element, then the element's attribute set does not contain a
+node for the attribute.</p>
+
+<p>An attribute node has an expanded name and has a string value. The
+expanded name consists of a local name and a possibly null URI (see
+<bibref ref="XMLNAMES"/>); the URI will be null if the specified
+attribute name did not have a prefix. The value is the normalized
+value as specified by the XML Recommendation <bibref ref="XML"/>. An
+attribute value whose value is of zero length is not treated
+specially.</p>
+
+<p>There are no attribute nodes for attributes that declare namespaces
+(see <bibref ref="XMLNAMES"/>).</p>
+
+<issue id="issue-external-dtd"><p>Should we specify something about
+how we expect XSL processors to process external DTDs and parameter
+entities? For example, what happens if an attribute default is
+declared in an external DTD?</p></issue>
+
+</div3>
+
+<div3 id="namespace-nodes">
+<head>Namespace Nodes</head>
+
+<p>Each element has an associated set of namespace nodes, one for each
+namespace prefix that is in scope for element and one for the default
+namespace if one is in scope for the element. This means that an
+element will have a namespace node:</p>
+
+<ulist>
+
+<item><p>for every attribute on the element whose name starts with
+<code>xmlns:</code>;</p></item>
+
+<item><p>for every attribute on an ancestor element whose name starts
+<code>xmlns:</code> unless the element itself or a nearer ancestor
+redeclares the prefix;</p></item>
+
+<item>
+
+<p>for an <code>xmlns</code> attribute, unless its value is the empty
+string.</p>
+
+<note><p>An attribute <code>xmlns=""</code> <quote>undeclares</quote>
+the default namespace (see <bibref ref="XMLNAMES"/>).</p></note>
+
+</item>
+
+</ulist>
+
+<p>A namespace node has a name which is a string giving the prefix.
+This is empty if the namespace node is for the default namespace. A
+namespace node also has a value which is the namespace URI. If the
+namespace declaration specifies a relative URI, then the resolved
+absolute URI is used as the value.</p>
+
+<p>When writing an element node in the result tree out as XML, an XSL
+processor must add sufficient namespace-declaring attributes to the
+start-tag to ensure that if a tree were recreated from the XML, then
+the set of namespace nodes on the element node in the recreated tree
+would be equal to or a superset of the set of namespace nodes of the
+element node in the result tree.</p>
+
+<note><p>The semantics of a document type may treat parts of attribute
+values or data content as namespace prefixes. The presence of
+namespace nodes ensures that the semantics can be preserved when the
+tree is written out as XML.</p></note>
+
+</div3>
+
+
+<div3>
+<head>Processing Instruction Nodes</head>
+
+<p>There is a processing instruction node for every processing
+instruction.</p>
+
+<ednote><edtext>What about processing instructions in the internal
+subset or elsewhere in the DTD?</edtext></ednote>
+
+<p>An processing instruction has a name. This is a string equal to
+the processing instruction's target. It also has a value. This is a
+string equal to the part of the processing instruction following the
+target and any whitespace. It does not include the terminating
+<code>?&gt;</code>.</p>
+
+</div3>
+
+<div3>
+<head>Comment Nodes</head>
+
+<p>There is a comment node for every comment.</p>
+
+<ednote><edtext>What about comments in the internal subset or
+elsewhere in the DTD?</edtext></ednote>
+
+<p>A comment has a value. This is a string equal to the text of the
+comment not including the opening <code>&lt;!--</code> or the closing
+<code>--&gt;</code>.</p>
+
+</div3>
+
+<div3>
+<head>Text Nodes</head>
+
+<p>Character data is grouped into text nodes. As much character data
+as possible is grouped into each text node: a text node never has an
+immediately following or preceding sibling that is a text node. The
+value of a text node is the character data.</p>
+
+<p>Each character within
+a CDATA section is treated as character data. Thus
+<code>&lt;![CDATA[&lt;]]&gt;</code> in the source document will
+treated the same as <code>&amp;lt;</code>. Characters inside comments
+or processing instructions are not character data. Line-endings in
+external entities are normalized to #xA as specified in the XML
+Recommendation <bibref ref="XML"/>.</p>
+
+</div3>
+
+<div3 id="strip">
+<head>Whitespace Stripping</head>
+
+<p>After the tree has been constructed, but before it is otherwise
+processed by XSL, some text nodes may be stripped. The
+stripping process takes as input a set of element types for which
+whitespace must be preserved. The stripping process is applied to
+both stylesheets and source documents, but the set of
+whitespace-preserving element types is determined differently for
+stylesheets and for source documents.</p>
+
+<p>A text node is preserved if any of the following apply:</p>
+
+<ulist>
+
+<item><p>The element type of the parent of the text node is in the set
+of whitespace-preserving element types.</p></item>
+
+<item><p>The text node contains at least one non-whitespace character.
+As in XML, a whitespace character is #x20, #x9, #xD or #xA.</p></item>
+
+<item><p>An ancestor element of the text node has an
+<code>xml:space</code> attribute with a value of
+<code>preserve</code>, and no closer ancestor element has
+<code>xml:space</code> with a value of
+<code>default</code>.</p></item>
+
+</ulist>
+
+<p>Otherwise the text node is stripped.</p>
+
+<p>The <code>xml:space</code> attributes are not stripped from the
+tree.</p>
+
+<note><p>This implies that if an <code>xml:space</code> attribute is
+specified on a literal result element, it will be included in the
+result.</p></note>
+
+<p>For stylesheets, the set of whitespace-preserving element types
+consists of just <code>xsl:text</code><!-- and <code>fo:text</code>-->.</p>
+
+<!--<note><p><code>fo:text</code> is a formatting object that can contain
+only characters. Whereas characters outside <code>fo:text</code> are
+subject to the XSL-defined whitespace-related formatting properties
+(such as collapsing adjacent whitespace characters) in the same way as
+characters in the source document, whitespace characters occurring in
+<code>fo:text</code> will not be collapsed or stripped by the
+formatter.</p></note>-->
+
+<p>For source documents, the set of whitespace-preserving element
+types is determined using the stylesheet as follows:</p>
+
+<ulist>
+
+<item><p>If the <code>xsl:stylesheet</code> element specifies a
+<code>default-space</code> attribute with a value of
+<code>strip</code>, then the set is initially empty. Otherwise the
+set initially contains all element types that occur in the
+document.</p></item>
+
+<item><p>The <code>xsl:strip-space</code> element causes an element
+type to be removed from the set of whitespace-preserving element types.
+The <code>element</code> attribute gives the name of the element
+type.</p></item>
+
+<item><p>The <code>xsl:preserve-space</code> element causes an element
+type to be added to the set whitespace-preserving element types. The
+<code>element</code> attribute gives the name of the element
+type.</p></item>
+
+</ulist>
+
+<issue id="issue-declare-multiple-elements"><p>Should the value of the
+<code>element</code> attribute of <code>xsl:strip-space</code>,
+<code>xsl:preserve-space</code> and <code>xsl:id</code> be a list of
+element type names (and thus be renamed to <code>elements</code>)? If
+so, should the <code>attribute</code> attribute of <code>xsl:id</code>
+also be a list of attribute names?</p></issue>
+
+<ednote><edtext>Clarify how these declarations interact with each
+other and with xsl:import.</edtext></ednote>
+
+<p>The <code>xsl:stylesheet</code> element can include an
+<code>indent-result</code> attribute with values <code>yes</code> or
+<code>no</code>. If the stylesheet specifies
+<code>indent-result="yes"</code>, then the XSL processor may add
+whitespace to the result tree (possibly based on whitespace stripped
+from either the source document or the stylesheet) in order to indent
+the result nicely; if <code>indent-result="no"</code>, it must not add
+any whitespace to the result. When adding whitespace with
+<code>indent-result="yes"</code>, the XSL processor can use any
+algorithm provided that the result is the same as the result with
+<code>indent-result="no"</code> after whitespace is stripped from both
+using the process described with the set of whitespace-preserving
+element types consisting of just <code>xsl:text</code><!-- and
+<code>fo:text</code>-->.</p>
+
+</div3>
+
+</div2>
+
+<div2>
+<head>Template Rules</head>
+
+<p>A template rule is specified with the <code>xsl:template</code>
+element. The <code>match</code> attribute identifies the source node
+or nodes to which the rule applies. The content of the
+<code>xsl:template</code> element is the template.</p>
+
+<p>For example, an XML document might contain:</p>
+
+<eg><![CDATA[This is an <emph>important</emph> point.]]></eg>
+
+<p>The following template rule matches elements of type
+<code>emph</code> and has a template which produces a
+<code>fo:sequence</code> formatting object with a
+<code>font-weight</code> property of <code>bold</code>.</p>
+
+<eg><![CDATA[<xsl:template match="emph">
+ <fo:sequence font-weight="bold">
+ <xsl:apply-templates/>
+ </fo:sequence>
+</xsl:template>
+]]></eg>
+
+<p>As described later, the <code>xsl:apply-templates</code> element
+recursively processes the children of the source element.</p>
+
+<div3 id="conflict">
+<head>Conflict Resolution for Template Rules</head>
+
+<p>It is possible for a source node to match more than one
+template rule. The template rule to be used is determined as
+follows:</p>
+
+<olist>
+
+<item><p>First, all matching template rules that are less
+<termref def="dt-important">important</termref> than the most
+important matching template rule or rules are eliminated from
+consideration.</p></item>
+
+<item><p>Next, all matching template rules that have a lower priority
+than the matching template rule or rules with the highest priority are
+eliminated from consideration. The priority of a rule is specified by
+the <code>priority</code> attribute on the rule. The value of this
+must be a real number (positive or negative). The default priority is
+0.</p>
+
+<ednote><edtext>Say exactly what syntax is allowed for real
+numbers.</edtext></ednote>
+
+</item>
+
+</olist>
+
+<p>It is an error if this leaves more than one matching template
+rule. An XSL processor may signal the error; if it does not signal
+the error, it must recover by choosing from amongst the matching
+template rules that are left the one that occurs last in the
+stylesheet.</p>
+
+</div3>
+
+<div3>
+<head>Built-in Template Rule</head>
+
+<p>There is a built-in template rule to allow recursive
+processing to continue in the absence of a successful pattern match by
+an explicit rule in the stylesheet. This rule applies to both element
+nodes and the root node. The following shows the equivalent of the
+built-in template rule:</p>
+
+<eg><![CDATA[<xsl:template match="*|/">
+ <xsl:apply-templates/>
+</xsl:template>]]></eg>
+
+<p>The built-in template rule is treated as if it were imported
+implicitly before the stylesheet and so is considered less <termref
+def="dt-important">important</termref> than all other template
+rules. Thus the author can override the built-in rule by including an
+explicit rule with <code>match="*|/"</code>.</p>
+
+<p>There is also a built-in template rule for text nodes
+that copies text through:</p>
+
+<eg><![CDATA[<xsl:template match="text()">
+ <xsl:value-of select="."/>
+</xsl:template>]]></eg>
+
+<p>The built-in rule does not apply to processing instructions and
+comments. When a comment or processing instruction is processed, and
+no rule is matched, nothing is created.</p>
+
+</div3>
+</div2>
+
+<div2>
+<head>Patterns</head>
+
+<div3>
+<head>Introduction</head>
+
+<p>This section introduces the syntax and semantics of XSL patterns.
+The formal, definitive specification is in the following section.</p>
+
+<p>A pattern is a string which selects a set nodes in a source
+document. The selection is relative to the current node. The
+simplest pattern is an element type name; it selects all the child
+elements of the current node with that element type name. For
+example, the pattern <code>chapter</code> selects all the chapter
+child elements of the current node.</p>
+
+<p>A pattern can also be matched against a node. If a node could be
+selected by a pattern, then the node is considered to match the
+pattern. More precisely, for any pattern and any document there is a
+matching set of nodes; this is the union, for each node in the
+document, of the set of nodes selected by the pattern with that node
+as the current node. For example, a pattern <code>chapter</code>
+matches any chapter element because if the current node was the parent
+of the chapter element, the chapter element would be one of the nodes
+selected by the pattern <code>chapter</code>. This includes the case
+where the <code>chapter</code> element is the document element,
+because the root node is the parent of the document element.</p>
+
+<p>The <code>|</code> operator can be used to express alternatives.
+For example, the pattern <code>emph|b</code> matches both
+<code>emph</code> elements and <code>b</code> elements.</p>
+
+<p>Patterns can be composed together with the <code>/</code> operator
+in a path-like manner. For example, a pattern
+<code>chapter/section</code> selects the <code>chapter</code> child
+elements of the current node, and then for each selected
+<code>chapter</code> element, selects the <code>section</code>
+children; in other words, it selects the <code>section</code>
+grandchildren of the current node that have <code>chapter</code>
+parents. A node would match a pattern <code>chapter/section</code> if
+it was a <code>section</code> element with a <code>chapter</code>
+parent.</p>
+
+<p><code>/</code> binds more tightly than <code>|</code>. Thus the
+pattern <code>ol/li|ul/li</code> matches <code>li</code> elements that
+have a <code>ol</code> or <code>ul</code> parent.</p>
+
+<p>Whitespace can be used around operators in patterns to improve
+readability. Thus <code>ol/li|ul/li</code> can be written as
+<code>ol/li | ul/li</code>.</p>
+
+<p><code>*</code> can be used instead of an element type name as a
+wildcard. For example, a pattern <code>*</code> would select all
+element children of the current node; a pattern <code>*/section</code>
+would select all <code>section</code> grandchildren of the current
+node. A pattern <code>chapter/*</code> would match any element that
+has a <code>chapter</code> parent.</p>
+
+<p>A <code>//</code> can be used instead of <code>/</code> to select
+from descendants instead of from children. For example, a pattern
+<code>chapter//p</code> selects all the <code>p</code> descendants of
+<code>chapter</code> children of the current node, and it matches all
+<code>p</code> elements that have a <code>chapter</code> ancestor.</p>
+
+<p>A pattern <code>.</code> selects the current node. This is useful
+with <code>//</code>. For example, <code>.//div</code> selects all
+<code>div</code> descendant elements of the current node.</p>
+
+<p>Similarily <code>..</code> selects the parent of the current node.
+For example, <code>../item</code> selects the <code>item</code>
+sibling elements of the current node.</p>
+
+<p>Other types of node are treated in a similar way to elements.</p>
+
+<ulist>
+
+<item><p>The attributes of an element are treated like the child
+elements; an attribute is distinguished from a child element by
+prefixing its name with <code>@</code>. For example,
+<code>@date</code> will select the <code>date</code> attribute of the
+current element; <code>employee/@salary</code> will select the
+<code>salary</code> attribute of each <code>employee</code> child
+element of the current node. A wildcard <code>@*</code> is allowed
+just as with elements; a pattern <code>@*</code> selects all
+attributes of the current node.</p></item>
+
+<item><p>A pattern <code>comment()</code> selects all comment children
+of the current node. Thus a pattern <code>comment()</code> will match
+any comment node.</p></item>
+
+<item><p>A pattern <code>pi()</code> selects all processing
+instruction children of the current node. An argument can be used to
+specify the target. Thus <code>pi("xml-stylesheet")</code> matches
+any processing instruction with a target <code>xml-stylesheet</code>.
+Note that the argument must be quoted.</p></item>
+
+</ulist>
+
+<p>The set of nodes selected by a pattern can be refined by following
+the pattern by a test in square brackets (<code>[]</code>). Each node
+in the set is tested. The result includes only those nodes for which
+test succeeds. The following are allowed as tests:</p>
+
+<ulist>
+
+<item><p>A pattern can be used a test; the test succeeds if the
+pattern selects one or more nodes when the node being tested is the
+current node. For example, a pattern <code>list[@type]</code> matches
+a <code>list</code> element with a <code>type</code> attribute; a
+pattern <code>book[editor]</code> selects <code>book</code> children
+elements of the current node that have at least one
+<code>editor</code> child element.</p></item>
+
+<item><p>A pattern can be compared to string. For example, a pattern
+<code>list[@type="ordered"]</code> would match any list with an
+attribute <code>type</code> with value <code>ordered</code>; a pattern
+<code>employee[location="USA"]</code> would select
+<code>employee</code> children of the current element that have a
+<code>location</code> child with content equal to
+<code>USA</code>.</p></item>
+
+<item><p>The position of a node relative to its siblings can be
+tested.</p>
+
+<ulist>
+
+<item><p><code>first-of-any()</code> succeeds if the node being tested
+is the first element child</p></item>
+
+<item><p><code>last-of-any()</code> succeeds if the node being tested
+is the last element child</p></item>
+
+<item><p><code>first-of-type()</code> succeeds if the node being
+tested is the first element child of its element type</p></item>
+
+<item><p><code>last-of-type()</code> succeeds if the node being
+tested is the first element child of its element type</p></item>
+
+</ulist>
+
+</item>
+
+<item><p>A test can be negated using <code>not()</code>. For example,
+<code>list[not(@type)]</code> matches any <code>list</code> element
+without a <code>type</code> attribute.</p></item>
+
+<item><p>Tests can be combined with <code>and</code> and
+<code>or</code>. For example,</p>
+
+<eg>back/div[first-of-type() and last-of-type()]</eg>
+
+<p>matches a <code>div</code> element with a <code>back</code> parent,
+when it is the only <code>div</code> child of its parent.</p>
+</item>
+
+</ulist>
+
+<p>The <code>[]</code> operator binds more tightly than
+<code>|</code>. Thus the pattern
+<code>ol|list[@type="ordered"]</code> matches either <code>list</code>
+elements with a <code>type</code> attribute with value
+<code>ordered</code> or <code>ol</code> elements.</p>
+
+<p>The root node is treated is specially. A <code>/</code> at the
+beginning of a pattern selects the root node (not the document
+element). For example, a pattern that is just <code>/</code> matches
+the root node; a pattern <code>/div</code> will match the document
+element it is a <code>div</code> element; a pattern <code>/*</code>
+will match the document element whatever is. When a pattern starts
+with <code>/</code> the current node is irrelevant.</p>
+
+<p>A pattern can also start with <code>//</code>. <code>//foo</code>
+means the same as <code>/.//foo</code>: it selects the
+<code>foo</code> descendants of the root node, which implies that it
+selects all foo elements. When a pattern starts with <code>//</code>
+the current node is irrelevant.</p>
+
+<p>The <code>ancestor</code> function allows selection of an ancestor
+of the current node. The argument is a match pattern. It selects the
+first ancestor of the current node that matches the argument. For
+example, <code>ancestor(chapter)/title</code> will select the
+<code>title</code> children of the first ancestor of the current node
+that is a <code>chapter</code>.</p>
+
+<p>The <code>id</code> function allows ID references to be followed.
+The argument can be a literal string. For example,
+<code>id('foo')</code> will select the element with ID
+<code>foo</code>; if there is no such element, the empty node set will
+be returned. Multiple whitespace separated IDs are also allowed; this
+<code>id('foo bar')</code> would select elements with an ID
+<code>foo</code> or <code>bar</code>. The argument can be a pattern
+instead of a literal string; for each node selected by the pattern,
+the value of the node is treated as whitespace separated list of ID
+references. For example, if the current node is an element with an
+IDREF or IDREFS attribute named <code>ref</code>, then a pattern
+<code>id(@ref)</code> would select the elements referenced by the
+<code>ref</code> attribute.</p>
+
+<ednote><edtext>Would it be less confusing to call this
+idref?</edtext></ednote>
+
+</div3>
+
+<div3>
+<head>Syntax and Semantics</head>
+
+<p>An expression is evaluated with respect to a context, which is a
+single node. The result of evaluating an expression is a set of nodes
+or a boolean.</p>
+
+<p>In the following grammar, the nonterminal <xnt
+href="&XMLNames;#NT-QName">QName</xnt> is defined in <bibref
+ref="XMLNAMES"/>, and <xnt href="&XMLRec;#NT-S">S</xnt> is defined in
+<bibref ref="XML"/>.</p>
+
+<scrap>
+<head>Selecting</head>
+<prod id="NT-SelectExpr">
+<lhs>SelectExpr</lhs>
+<rhs><nt def="NT-UnionExpr">UnionExpr</nt></rhs>
+</prod>
+</scrap>
+
+<p><termdef id="dt-select-pattern" term="Select Pattern">A
+<term>select pattern</term> must match the production for <nt
+def="NT-SelectExpr">SelectExpr</nt>; it returns the list of nodes that
+results from evaluating the <nt def="NT-SelectExpr">SelectExpr</nt>
+with the current node as context; the nodes are in the list are in
+<termref def="dt-document-order">document
+order</termref>.</termdef></p>
+
+<scrap>
+<head>Matching</head>
+<prod id="NT-MatchExpr">
+<lhs>MatchExpr</lhs>
+<rhs><nt def="NT-SelectExpr">SelectExpr</nt></rhs>
+</prod>
+</scrap>
+
+<p><termdef id="dt-match-pattern" term="Match Pattern">A <term>match
+pattern</term> must match the production for <nt
+def="NT-MatchExpr">MatchExpr</nt>; a node matches the match pattern if
+the <nt def="NT-MatchExpr">MatchExpr</nt> returns true when evaluated
+with that node as context.</termdef></p>
+
+<p>The result of the <nt def="NT-MatchExpr">MatchExpr</nt> is true if,
+for any node in the document that contains the context of the <nt
+def="NT-MatchExpr">MatchExpr</nt>, the result of evaluating the <nt
+def="NT-SelectExpr">SelectExpr</nt> with that node as context contains
+the context of the <nt def="NT-MatchExpr">MatchExpr</nt>. Otherwise
+the result is false.</p>
+
+<p>For implementation reasons, the functionality of <nt
+def="NT-MatchExpr">MatchExpr</nt>s is restricted as follows:</p>
+
+<ulist>
+
+<item><p>Within a <nt def="NT-BooleanExpr">BooleanExpr</nt> in a <nt
+def="NT-MatchExpr">MatchExpr</nt>, a <nt
+def="NT-SelectExpr">SelectExpr</nt> must be a <nt
+def="NT-NodeExpr">SubNodeExpr</nt>. More informally, within
+<code>[]</code> in a match pattern, <code>/</code>, <code>//</code>
+and <code>[]</code> must not be used. For example,
+<code>foo[bar/baz]</code> is not allowed as a match
+pattern.</p></item>
+
+<item><p>Within a <nt def="NT-MatchExpr">MatchExpr</nt>, an <nt
+def="NT-OtherNodeExpr">OtherNodeExpr</nt> must be a <nt
+def="NT-ConstantIdExpr">ConstantIdExpr</nt>.</p></item>
+
+</ulist>
+
+<scrap>
+<head>Unions</head>
+<prod id="NT-UnionExpr">
+<lhs>UnionExpr</lhs>
+<rhs><nt def="NT-PathExpr">PathExpr</nt></rhs>
+<rhs>| ( <nt def="NT-PathExpr">PathExpr</nt> '|' <nt def="NT-UnionExpr">UnionExpr</nt>)</rhs>
+</prod>
+</scrap>
+
+<p>The context of the right hand side expressions is the context of
+the left hand side expression. The results of the right hand side
+expressions are node sets. The result of the left hand side <nt
+def="NT-UnionExpr">UnionExpr</nt> is the union of the results of the
+right hand side expressions.</p>
+
+<scrap>
+<head>Paths</head>
+<prod id="NT-PathExpr">
+<lhs>PathExpr</lhs>
+<rhs><nt def="NT-AbsolutePathExpr">AbsolutePathExpr</nt></rhs>
+<rhs>| <nt def="NT-ComposeExpr">ComposeExpr</nt></rhs>
+</prod>
+</scrap>
+
+<p>The context of the right hand side expressions is the context of
+the left hand side expression. The result of the left hand side is
+the result of the right hand side. The result is a node set.</p>
+
+<scrap>
+<head>Absolute Paths</head>
+<prod id="NT-AbsolutePathExpr">
+<lhs>AbsolutePathExpr</lhs>
+<rhs>'/' <nt def="NT-SubtreeExpr">SubtreeExpr</nt>?</rhs>
+</prod>
+</scrap>
+
+<p>If the <nt def="NT-SubtreeExpr">SubtreeExpr</nt> is present, then
+the context for the <nt def="NT-SubtreeExpr">SubtreeExpr</nt> is the
+root node, and the result is the result of the <nt
+def="NT-SubtreeExpr">SubtreeExpr</nt>. Otherwise the result is the
+root node.</p>
+
+<scrap>
+<head>Subtrees</head>
+<prod id="NT-SubtreeExpr">
+<lhs>SubtreeExpr</lhs>
+<rhs>'/'? <nt def="NT-ComposeExpr">ComposeExpr</nt></rhs>
+</prod>
+</scrap>
+
+<p>If the <code>/</code> is present, then the result <nt
+def="NT-SubtreeExpr">SubtreeExpr</nt> is the union, for each node in
+the subtree rooted at the context of the <nt
+def="NT-SubtreeExpr">SubtreeExpr</nt>, of the result of evaluating the
+<nt def="NT-ComposeExpr">ComposeExpr</nt> with that node as context.
+Otherwise the <nt def="NT-SubtreeExpr">SubtreeExpr</nt> is equivalent
+to <nt def="NT-ComposeExpr">ComposeExpr</nt>.</p>
+
+<scrap>
+<head>Composition</head>
+<prod id="NT-ComposeExpr">
+<lhs>ComposeExpr</lhs>
+<rhs><nt def="NT-FilterExpr">FilterExpr</nt></rhs>
+<rhs>| (<nt def="NT-FilterExpr">FilterExpr</nt> '/' <nt def="NT-SubtreeExpr">SubtreeExpr</nt>)</rhs>
+</prod>
+</scrap>
+
+<p>The context of the <nt def="NT-FilterExpr">FilterExpr</nt> is the
+context of the <nt def="NT-ComposeExpr">ComposeExpr</nt>. If the <nt
+def="NT-SubtreeExpr">SubtreeExpr</nt> is present, then, for each node
+in the result of the <nt def="NT-FilterExpr">FilterExpr</nt>, the <nt
+def="NT-SubtreeExpr">SubtreeExpr</nt> is evaluated with that node as
+the context; the result of the <nt def="NT-ComposeExpr">ComposeExpr</nt>
+is the union of the results of evaluating the <nt
+def="NT-SubtreeExpr">SubtreeExpr</nt>. Otherwise the result is the
+result of the <nt def="NT-FilterExpr">FilterExpr</nt>.</p>
+
+<scrap>
+<head>Filtering</head>
+<prod id="NT-FilterExpr">
+<lhs>FilterExpr</lhs>
+<rhs><nt def="NT-NodeExpr">NodeExpr</nt>
+( '[' <nt def="NT-BooleanExpr">BooleanExpr</nt> ']' )?</rhs>
+</prod>
+</scrap>
+
+<p>The context of the <nt def="NT-NodeExpr">NodeExpr</nt> is the
+context of the <nt def="NT-FilterExpr">FilterExpr</nt>. If the <nt
+def="NT-BooleanExpr">BooleanExpr</nt> is present, then for each node
+in the result of the <nt def="NT-NodeExpr">NodeExpr</nt>, the <nt
+def="NT-BooleanExpr">BooleanExpr</nt> is evaluated with that node as
+context; the result consists of those nodes for which the <nt
+def="NT-BooleanExpr">BooleanExpr</nt> evaluates to true.</p>
+
+<scrap>
+<head>Selecting Nodes</head>
+<prod id="NT-NodeExpr">
+<lhs>NodeExpr</lhs>
+<rhs><nt def="NT-SubNodeExpr">SubNodeExpr</nt></rhs>
+<rhs>| <nt def="NT-OtherNodeExpr">OtherNodeExpr</nt></rhs>
+</prod>
+<prod id="NT-SubNodeExpr">
+<lhs>SubNodeExpr</lhs>
+<rhs><nt def="NT-ElementExpr">ElementExpr</nt></rhs>
+<rhs>| <nt def="NT-AttributeExpr">AttributeExpr</nt></rhs>
+<rhs>| <nt def="NT-TextExpr">TextExpr</nt></rhs>
+<rhs>| <nt def="NT-CommentExpr">CommentExpr</nt></rhs>
+<rhs>| <nt def="NT-PiExpr">PiExpr</nt></rhs>
+</prod>
+<prod id="NT-OtherNodeExpr">
+<lhs>OtherNodeExpr</lhs>
+<rhs><nt def="NT-IdExpr">IdExpr</nt></rhs>
+<rhs>| <nt def="NT-AncestorExpr">AncestorExpr</nt></rhs>
+<rhs>| <nt def="NT-IdentityExpr">IdentityExpr</nt></rhs>
+<rhs>| <nt def="NT-ParentExpr">ParentExpr</nt></rhs>
+</prod>
+</scrap>
+
+<p>The context of the right hand side expressions is the context of
+the left hand side expression. The results of the right hand side
+expressions are node sets. The result of the left hand side is the
+result of the left hand side expression.</p>
+
+<issue id="issue-multiple-sources"><p>Should it be possible for
+patterns to select nodes in documents other than the source
+document?</p></issue>
+
+<issue id="issue-sibling-qual"><p>Should there be qualifiers that
+constrain an element to have an immediately preceding or following
+sibling of a particular type?</p></issue>
+
+<scrap>
+<head>Elements</head>
+<prod id="NT-ElementExpr">
+<lhs>ElementExpr</lhs>
+<rhs><xnt href="&XMLNames;#NT-QName">QName</xnt></rhs>
+<rhs>| '*'</rhs>
+</prod>
+</scrap>
+
+<p>If <code>*</code> is specified, then the result is the child
+elements of the context of the <nt
+def="NT-ElementExpr">ElementExpr</nt>. Otherwise, the result is the
+set of all elements that are the children of the context of <nt
+def="NT-ElementExpr">ElementExpr</nt> and whose name is equal to <xnt
+href="&XMLNames;#NT-QName">QName</xnt>.</p>
+
+<p>When comparing the name of an element to a <xnt
+href="&XMLNames;#NT-QName">QName</xnt>, the <xnt
+href="&XMLNames;#NT-QName">QName</xnt> is expanded into a local name
+and a possibly null URI. This expansion is done in the same way as
+for element type names in start and end-tags except that the the
+default namespace declared with <code>xmlns</code> is not used: if the
+<xnt href="&XMLNames;#NT-QName">QName</xnt> does not have a prefix,
+then the URI is null (this is the same way attribute names are
+expanded). The expanded element type names are are compared (see
+<specref ref="element-nodes"/>).</p>
+
+<issue id="issue-pattern-namespace-wildcards"><p>Should patterns of
+the form <code>foo:*</code> or <code>*:foo</code> be allowed? If so,
+should <code>*</code> match any element or any element without a
+namespace URI?</p></issue>
+
+<scrap>
+<head>Attributes</head>
+<prod id="NT-AttributeExpr">
+<lhs>AttributeExpr</lhs>
+<rhs>('@' <xnt href="&XMLNames;#NT-QName">QName</xnt>)</rhs>
+<rhs>| ('@' '*')</rhs>
+</prod>
+</scrap>
+
+<p>If <code>*</code> is specified, the result is the set of attribute
+nodes of the context of the <nt
+def="NT-AttributeExpr">AttributeExpr</nt>. If a <xnt
+href="&XMLNames;#NT-QName">QName</xnt> is specified, the result is the
+attribute node of the context of the <nt
+def="NT-AttributeExpr">AttributeExpr</nt> named <xnt
+href="&XMLNames;#NT-QName">QName</xnt>, or the empty node set if there
+is no such attribute node. When matching attribute names, the
+expanded names are compared (see <specref
+ref="attribute-nodes"/>). The <xnt
+href="&XMLNames;#NT-QName">QName</xnt> is expanded in the same way as
+a <xnt href="&XMLNames;#NT-QName">QName</xnt> in an <nt
+def="NT-ElementExpr">ElementExpr</nt>.</p>
+
+<issue id="issue-attribute-qual-case"><p>Do we need to be able
+to match attributes in a case insensitive way?</p></issue>
+
+<scrap>
+<head>Processing Instructions</head>
+<prod id="NT-PiExpr">
+<lhs>PiExpr</lhs>
+<rhs>'pi(' <nt def="NT-Literal">Literal</nt>? ')'</rhs>
+</prod>
+</scrap>
+
+<p>If the <nt def="NT-Literal">Literal</nt> is present, the result is
+the set of processing instruction nodes which are children of the
+context of the <nt def="NT-PiExpr">PiExpr</nt> and whose target is
+equal to the value of <nt def="NT-Literal">Literal</nt>. Otherwise
+the result is the set of processing instruction nodes which are
+children of the context of the <nt def="NT-PiExpr">PiExpr</nt>.</p>
+
+<scrap>
+<head>Text</head>
+<prod id="NT-TextExpr">
+<lhs>TextExpr</lhs>
+<rhs>'text(' ')'</rhs>
+</prod>
+</scrap>
+
+<p>The result is the set of all text nodes whose parent is a node in
+the context of the <nt def="NT-TextExpr">TextExpr</nt>.</p>
+
+<issue id="issue-regex"><p>Should XSL support regular
+expressions for matching against any or all of pcdata content,
+attribute values, attribute names, element type names?</p></issue>
+
+
+<scrap>
+<head>Comments</head>
+<prod id="NT-CommentExpr">
+<lhs>CommentExpr</lhs>
+<rhs>'comment(' ')'</rhs>
+</prod>
+</scrap>
+
+<p>The result is the set of all comment nodes which are children of
+the context of the <nt def="NT-CommentExpr">CommentExpr</nt>.</p>
+
+<scrap>
+<head>IDs</head>
+<prod id="NT-IdExpr">
+<lhs>IdExpr</lhs>
+<rhs><nt def="NT-ConstantIdExpr">ConstantIdExpr</nt></rhs>
+<rhs>| <nt def="NT-VariableIdExpr">VariableIdExpr</nt></rhs>
+</prod>
+<prod id="NT-ConstantIdExpr">
+<lhs>ConstantIdExpr</lhs>
+<rhs>'id(' <nt def="NT-Literal">Literal</nt> ')'</rhs>
+</prod>
+<prod id="NT-VariableIdExpr">
+<lhs>VariableIdExpr</lhs>
+<rhs>'id(' <nt def="NT-SelectExpr">SelectExpr</nt> ')'</rhs>
+</prod>
+</scrap>
+
+<p>The context of the <nt def="NT-SelectExpr">SelectExpr</nt> is the
+context of the <nt def="NT-IdExpr">IdExpr</nt>. A set of names is
+computed from the argument as follows:</p>
+
+<ulist>
+
+<item><p>If it is a <nt def="NT-ConstantIdExpr">ConstantIdExpr</nt>, then
+the value of the <nt def="NT-Literal">Literal</nt> is treated as a
+whitespace-separated list of names; the set of names are the members
+of the list.</p></item>
+
+<item><p>Otherwise, the value of each node in the result of the <nt
+def="NT-SelectExpr">SelectExpr</nt> is treated as a
+whitespace-separated list of names; the set of names is the union for
+each node of the members of the list.</p></item>
+
+</ulist>
+
+<p>The result is the set of element nodes whose ID (see <specref
+ref="unique-id"/>) is one of the names in the set of names specified
+by the argument.</p>
+
+<issue id="issue-class-attribute"><p>Should there be a way of
+specifying that an attribute serves as a class attribute and then
+pattern syntax that treats class attributes specially?</p></issue>
+
+<scrap>
+<head>Ancestors</head>
+<prod id="NT-AncestorExpr">
+<lhs>AncestorExpr</lhs>
+<rhs>'ancestor(' <nt def="NT-MatchExpr">MatchExpr</nt> ')'</rhs>
+</prod>
+</scrap>
+
+<p>The result the first ancestor of the context of the <nt
+def="NT-AncestorExpr">AncestorExpr</nt> such that <nt
+def="NT-MatchExpr">MatchExpr</nt>, when evaluated with that ancestor
+as the context, has a result of true. If there is no such ancestor,
+the result is the empty node set.</p>
+
+<scrap>
+<head>Identity</head>
+<prod id="NT-IdentityExpr">
+<lhs>IdentityExpr</lhs>
+<rhs>'.'</rhs>
+</prod>
+</scrap>
+
+<p>The result is the context of the <nt
+def="NT-IdentityExpr">IdentityExpr</nt>.</p>
+
+<scrap>
+<head>Parents</head>
+<prod id="NT-ParentExpr">
+<lhs>ParentExpr</lhs>
+<rhs>'..'</rhs>
+</prod>
+</scrap>
+
+<p>The result is the parent of the context of the <nt
+def="NT-ParentExpr">ParentExpr</nt>. If the context is the root node,
+then the result is the empty node set.</p>
+
+<scrap>
+<head>Boolean Expressions</head>
+<prod id="NT-BooleanExpr">
+<lhs>BooleanExpr</lhs>
+<rhs><nt def="NT-AndExpr">AndExpr</nt></rhs>
+<rhs>| <nt def="NT-OrExpr">OrExpr</nt></rhs>
+<rhs>| <nt def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt></rhs>
+</prod>
+<prod id="NT-BooleanPrimaryExpr">
+<lhs>BooleanPrimaryExpr</lhs>
+<rhs><nt def="NT-BooleanGroupExpr">BooleanGroupExpr</nt></rhs>
+<rhs>| <nt def="NT-NotExpr">NotExpr</nt></rhs>
+<rhs>| <nt def="NT-PositionalExpr">PositionalExpr</nt></rhs>
+<rhs>| <nt def="NT-TestExpr">TestExpr</nt></rhs>
+<rhs>| <nt def="NT-EqualityExpr">EqualityExpr</nt></rhs>
+</prod>
+</scrap>
+
+<p>The result of a <nt def="NT-BooleanExpr">BooleanExpr</nt> is true
+or false. The context of the right hand side
+expressions is the context of the <nt
+def="NT-BooleanExpr">BooleanExpr</nt>. The result of the <nt
+def="NT-BooleanExpr">BooleanExpr</nt> is the result of the right hand
+side.</p>
+
+<scrap>
+<head>And</head>
+<prod id="NT-AndExpr">
+<lhs>AndExpr</lhs>
+<rhs><nt def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt> ( 'and' <nt def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt> )+</rhs>
+</prod>
+</scrap>
+
+<p>The context for each <nt
+def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt> is the context of
+the <nt def="NT-AndExpr">AndExpr</nt>. The result is true if the
+result of all of the <nt
+def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt>s is true;
+otherwise the result is false.</p>
+
+<scrap>
+<head>Or</head>
+<prod id="NT-OrExpr">
+<lhs>OrExpr</lhs>
+<rhs><nt def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt> ( 'or' <nt def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt> )+</rhs>
+</prod>
+</scrap>
+
+<p>The context for each <nt
+def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt> is the context of
+the <nt def="NT-OrExpr">OrExpr</nt>. The result is true if the result
+of any of the <nt def="NT-BooleanPrimaryExpr">BooleanPrimaryExpr</nt>s
+is true; otherwise the result is false.</p>
+
+<scrap>
+<head>Grouping</head>
+<prod id="NT-BooleanGroupExpr">
+<lhs>BooleanGroupExpr</lhs>
+<rhs>'(' <nt def="NT-BooleanExpr">BooleanExpr</nt> ')'</rhs>
+</prod>
+</scrap>
+
+<p>The result of the left hand side is the result of the right hand
+side. The context of the right hand side is the context of the left
+hand side.</p>
+
+<scrap>
+<head>Negation</head>
+<prod id="NT-NotExpr">
+<lhs>NotExpr</lhs>
+<rhs>'not(' <nt def="NT-BooleanExpr">BooleanExpr</nt> ')'</rhs>
+</prod>
+</scrap>
+
+<p>The result of the <nt def="NT-NotExpr">NotExpr</nt> is true if the
+result of the <nt def="NT-BooleanExpr">BooleanExpr</nt> is false;
+otherwise the result is false.</p>
+
+<scrap>
+<head>Position</head>
+<prod id="NT-PositionalExpr">
+<lhs>PositionalExpr</lhs>
+<rhs>'first-of-type(' ')'</rhs>
+<rhs>| 'last-of-type(' ')'</rhs>
+<rhs>| 'first-of-any(' ')'</rhs>
+<rhs>| 'last-of-any(' ')'</rhs>
+</prod>
+</scrap>
+
+<p>The context of the <nt def="NT-PositionalExpr">PositionalExpr</nt>
+is a single node.</p>
+
+<ulist>
+
+<item><p>For <code>first-of-type()</code>, the result is true if the
+context node is an element and the element has no preceding siblings
+that are elements with the same element type name, and false
+otherwise.</p></item>
+
+<item><p>For <code>first-of-any()</code>, the result is true if the
+context node is an element and the element has no preceding siblings
+that are elements, and false otherwise.</p></item>
+
+<item><p>For <code>last-of-type()</code>, the result is true if the
+context node is an element and the element has no following siblings
+that are elements with the same element type name, and false
+otherwise.</p></item>
+
+<item><p>For <code>last-of-any()</code>, the result is true if the
+context node is an element and the element has no following siblings
+that are elements, and false
+otherwise.</p></item>
+
+</ulist>
+
+<scrap>
+<head>Testing Existence</head>
+<prod id="NT-TestExpr">
+<lhs>TestExpr</lhs>
+<rhs><nt def="NT-SelectExpr">SelectExpr</nt></rhs>
+</prod>
+</scrap>
+
+<p>The context of the <nt def="NT-SelectExpr">SelectExpr</nt> is the
+context of the <nt def="NT-EqualityExpr">EqualityExpr</nt>. The
+result of the <nt def="NT-TestExpr">TestExpr</nt> is true if the
+result of the <nt def="NT-SelectExpr">SelectExpr</nt> is non-empty.
+Otherwise the result is false.</p>
+
+<scrap>
+<head>Equality</head>
+<prod id="NT-EqualityExpr">
+<lhs>EqualityExpr</lhs>
+<rhs><nt def="NT-SelectExpr">SelectExpr</nt> '=' <nt def="NT-Literal">Literal</nt></rhs>
+</prod>
+</scrap>
+
+<p>The context of the <nt def="NT-SelectExpr">SelectExpr</nt> is the
+context of the <nt def="NT-EqualityExpr">EqualityExpr</nt>. The
+result is true if there is a node in the result of the <nt
+def="NT-SelectExpr">SelectExpr</nt> whose value is equal to the value
+of the <nt def="NT-Literal">Literal</nt>.</p>
+
+<ednote><edtext>We plan to use the data-typing facilities being
+developed by the XML Schema WG to allow ordered
+comparisons.</edtext></ednote>
+
+<scrap>
+<head>Literal</head>
+<prod id="NT-Literal">
+<lhs>Literal</lhs>
+<rhs>'"' [^"]* '"'</rhs>
+<rhs>| "'" [^']* "'"</rhs>
+</prod>
+</scrap>
+
+<p>The value of the <nt def="NT-Literal">Literal</nt> is the sequence
+of characters inside the <code>"</code> or <code>'</code>
+characters>.</p>
+
+<scrap>
+<head>Pattern Lexical Structure</head>
+<prod id="NT-PatternToken">
+<lhs>PatternToken</lhs>
+<rhs>'/' | '@' | '(' | ')' | '|' | '[' | ']' | ',' | '=' | '.' | '..' | '*'</rhs>
+<rhs>| 'id(' | 'ancestor(' | 'comment(' | 'pi(' | 'text(' | 'not(' </rhs>
+<rhs>| 'first-of-type(' </rhs>
+<rhs>| 'last-of-type(' </rhs>
+<rhs>| 'first-of-any(' </rhs>
+<rhs>| 'last-of-any(' </rhs>
+<rhs>| <xnt href="&XMLNames;#NT-QName">QName</xnt></rhs>
+<rhs>| <nt def="NT-Literal">Literal</nt></rhs>
+</prod>
+<prod id="NT-PatternWhitespace">
+<lhs>PatternWhitespace</lhs>
+<rhs><xnt href="&XMLRec;#NT-S">S</xnt></rhs>
+</prod>
+</scrap>
+
+<p>For readability, whitespace may be used in patterns even though not
+explicitly allowed by the grammar: <nt
+def="NT-PatternWhitespace">PatternWhitespace</nt> may be freely added
+within patterns before or after any <nt
+def="NT-PatternToken">PatternToken</nt>.</p>
+
+</div3>
+
+</div2>
+
+<div2>
+<head>Templates</head>
+
+<div3>
+<head>Overview</head>
+
+<p>When the rule that is to be applied to the source element has been
+identified, the rule's template is instantiated. A
+template can contain literal result elements, character data and
+instructions for creating fragments of the result tree. Instructions
+are represented by elements in the XSL namespace.</p>
+
+<p>The <code>xsl:apply-templates</code> instruction can select
+descendant nodes for processing. Without any attribute, the
+<code>xsl:apply-templates</code> instruction processes the immediate
+children nodes of the source element; a <code>select</code> attribute
+can be used to process nodes selected by a specified pattern.</p>
+
+<eg><![CDATA[<xsl:template match="chapter/title">
+ <fo:rule-graphic/>
+ <fo:block space-before="2pt">
+ <xsl:text>Chapter </xsl:text>
+ <xsl:number/>
+ <xsl:text>: </xsl:text>
+ <xsl:apply-templates/>
+ </fo:block>
+ <fo:rule-graphic/>
+</xsl:template>]]></eg>
+
+<issue id="issue-instruction-error"><p>Should there be an instruction
+that generates an error, like the <code>error</code> procedure in
+DSSSL?</p></issue>
+
+<issue id="issue-multiple-results"><p>Should it be possible to create
+multiple result trees?</p></issue>
+
+</div3>
+
+<div3>
+<head>Creating Elements and Attributes</head>
+
+<div4>
+<head>Literal Result Elements</head>
+
+<p>In a template an element in the stylesheet that does not belong to
+the XSL namespace is instantiated to create an element node of the
+same type. The created element node will have the attribute nodes
+that were present on the element node in the stylesheet tree. The
+created element node will also have the namespace nodes that were
+present on the element node in the stylesheet tree with the exception
+of any namespace node whose value is the XSL namespace URI
+(<code>http://www.w3.org/TR/WD-xsl</code>).</p>
+
+<p>The value of an attribute of a literal result element is
+interpreted as an <termref def="dt-attribute-value-template">attribute
+value template</termref>: it can contain string expressions contained
+in curly braces (<code>{}</code>).</p>
+
+<p>Namespace URIs that occur literally in the stylesheet and that are
+being used to create nodes in the result tree can be quoted. This
+applies to:</p>
+
+<ulist>
+
+<item><p>the namespace URI in the expanded name of an literal
+result element in the stylesheet</p></item>
+
+<item><p>the namespace URI in the expanded name of an attribute
+specified on a literal result element in the stylesheet</p></item>
+
+<item><p>the value of a namespace node on a literal result element in
+the stylesheet</p></item>
+
+</ulist>
+
+<p>A namespace URI is quoted by prefixing it with the string
+<code>quote:</code>. This prefix will be removed when the template is
+instantiated to create the result element node with its associated
+attribute nodes and namespace nodes.</p>
+
+<p>When literal result elements are being used to create element,
+attribute and namespace nodes which use the XSL namespace URI, the
+namespace must be quoted to avoid misinterpretation by the XSL
+processor.</p>
+
+<note><p>It may be necessary also to quote other namespaces. For
+example, literal result elements belonging to a namespace dealing with
+digital signatures might cause XSL stylesheets to mishandled by
+general purpose security software; quoting the namespace would avoid
+the possibility of such mishandling.</p></note>
+
+<p>For example, the stylesheet</p>
+
+<eg><![CDATA[<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/TR/WD-xsl"
+ xmlns:fo="http://www.w3.org/TR/WD-xsl/FO"
+ xmlns:qxsl="quote:http://www.w3.org/TR/WD-xsl">
+
+<xsl:template match="/">
+ <qxsl:stylesheet>
+ <xsl:apply-templates/>
+ </qxsl:stylesheet>
+</xsl:template>
+
+<xsl:template match="block">
+ <qxsl:template match="{.}">
+ <fo:block><qxsl:apply-templates/></fo:block>
+ </qxsl:template>
+</xsl:template>
+
+</xsl:stylesheet>]]></eg>
+
+<p>will generate an XSL stylesheet from a document of the form:</p>
+
+<eg><![CDATA[<elements>
+<block>p</block>
+<block>h1</block>
+<block>h2</block>
+<block>h3</block>
+<block>h4</block>
+</elements>]]></eg>
+
+</div4>
+
+<div4>
+
+<head>Named Attribute Sets</head>
+
+<p>The <code>xsl:attribute-set</code> element defines a named set of
+attributes. The <code>name</code> attribute specifies the name of the
+attribute set. The content of the <code>xsl:attribute-set</code>
+element consists of <code>xsl:attribute</code> elements that specify
+attributes. A literal result element can specify an attribute set name
+as the value of the <code>xsl:use</code> attribute.</p>
+
+<p>The following example creates a named attribute set
+<code>title-style</code> and uses it in a template rule.</p>
+
+<eg><![CDATA[<xsl:attribute-set name="title-style">
+ <xsl:attribute name="font-size">12pt</xsl:attribute>
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+</xsl:attribute-set>
+
+<xsl:template match="chapter/heading">
+ <fo:block xsl:use="title-style" quadding="start">
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>]]></eg>
+
+<p>If the <code>xsl:use</code> attribute is specified on an element
+that also specifies a value for an attribute that is also part of the
+attribute set named by <code>xsl:use</code>, the attribute in the
+named attribute set is not used.</p>
+
+<p>Multiple definitions of an attribute set with the same name are
+merged. An attribute from a definition that is more <termref
+def="dt-important">important</termref> takes precedence over an
+attribute from a definition that is less <termref
+def="dt-important">important</termref>. It is an error if there are
+two attribute sets with the same name that are equally important and
+that both contain the same attribute unless there is a more <termref
+def="dt-important">important</termref> definition of the attribute set
+that also contains the attribute. An XSL processor may signal the
+error; if it does not signal the error, it must recover by choosing
+from amongst the most important definitions that specify the attribute
+the one that was specified last in the stylesheet.</p>
+
+<p>An <code>xsl:use</code> attribute may specify a list of attribute
+set names separated by whitespace. These attribute sets will be
+merged treating the list as being in order of increasing
+importance.</p>
+
+</div4>
+
+<div4>
+<head>Creating Elements with <code>xsl:element</code></head>
+
+<p>The <code>xsl:element</code> allows an element to be created with a
+computed name. The <code>xsl:element</code> attribute has a required
+<code>name</code> attribute that specifies the name of the element.
+The <code>name</code> attribute is interpreted as an <termref
+def="dt-attribute-value-template">attribute value template</termref>.
+It is instantiated to create an element with the specified name. The
+content of the <code>xsl:element</code> element is a template for the
+attributes and children of the created element.</p>
+
+<p>The value of the <code>name</code> attribute after instantiation
+must have one of two forms:</p>
+
+<ulist>
+
+<item><p>It can be a <xnt href="&XMLNames;#NT-QName">QName</xnt>. In
+this case the name is expanded in the same way as an element type name
+using the namespace declarations in scope for the
+<code>xsl:element</code> element in the stylesheet.</p></item>
+
+<item><p>It can be a namespace URI followed by a <code>#</code>
+character followed by an <xnt
+href="&XMLNames;#NT-NCName">NCName</xnt>. This can be used
+conjunction with a <nt def="NT-NameExpr">NameExpr</nt> to compute a
+qualified name.</p></item>
+
+</ulist>
+
+</div4>
+
+<div4>
+<head>Creating Attributes with <code>xsl:attribute</code></head>
+
+<p>The <code>xsl:attribute</code> element can be used to add
+attributes to result elements whether created by literal result
+elements in the stylesheet or by <code>xsl:element</code> elements.
+The <code>xsl:element</code> attribute has a required
+<code>name</code> attribute that specifies the name of the attribute.
+The <code>name</code> attribute is interpreted as an <termref
+def="dt-attribute-value-template">attribute value template</termref>
+It adds an attribute node to the containing result element node. The
+content of the <code>xsl:attribute</code> element is a template for
+the value of the created attribute.</p>
+
+<p>The following are all errors:</p>
+
+<ulist>
+
+<item><p>Adding an attribute to an element after children have been
+added to it; implementations may either signal the error or ignore the
+attribute.</p></item>
+
+<item><p>Including nodes other than text nodes in the value of an
+attribute; implementations may either signal the error or ignore the
+added nodes.</p></item>
+
+<item><p>Adding an attribute that has the same name as an attribute
+already added; implementations may either signal the error or ignore
+the duplicate attribute.</p></item>
+
+<item><p>Adding an attribute to a node that is not an element;
+implementations may either signal the error or ignore the
+attribute.</p></item>
+
+</ulist>
+
+</div4>
+
+</div3>
+
+<div3>
+
+<head>Creating Text</head>
+
+<p>A template can also contain text nodes. Each text node in a
+template remaining after whitespace has been stripped as specified in
+<specref ref="strip"/> will create a text node with the same value in
+the result tree. Adjacent text nodes in the result tree are
+automatically merged.</p>
+
+<p>Note that text is processed at the tree level. Thus, markup of
+<code>&amp;lt;</code> in a template will be represented in the
+stylesheet tree by a text node that includes the character
+<code>&lt;</code>. This will create a text node in the result tree
+that contains a <code>&lt;</code> character, which will be represented
+by the markup <code>&amp;lt;</code> (or an equivalent character
+reference) when the result tree is externalized as an XML
+document.</p>
+
+<p>Literal data characters may also be wrapped in an
+<code>xsl:text</code> element. This wrapping may change what
+whitespace characters are stripped (see <specref ref="strip"/>) but
+does not affect how the characters are handled by the XSL processor
+thereafter.</p>
+
+</div3>
+
+
+<div3>
+<head>Creating Processing Instructions</head>
+
+<p>The <code>xsl:pi</code> element is instantiated to create a
+processing instruction node. The content of the <code>xsl:pi</code>
+element is a template for the value of the processing instruction
+node. The <code>xsl:pi</code> element has a required
+<code>name</code> attribute that specifies the name of the processing
+instruction node. The value of the name attribute is interpreted as
+an <termref def="dt-attribute-value-template">attribute value
+template</termref>.</p>
+
+<p>For example, this</p>
+
+<eg><![CDATA[<xsl:pi name="xml-stylesheet">href="book.css" type="text/css"</xsl:pi>]]></eg>
+
+<p>would create the processing instruction</p>
+
+<eg><![CDATA[<?xml-stylesheet href="book.css" type="text/css"?>]]></eg>
+
+<p>It is an error if instantiating the content of <code>xsl:pi</code>
+creates anything other than characters. An XSL processor may signal
+the error; if it does not signal the error, it must recover by
+ignoring the offending nodes together with their content.</p>
+
+<p>It is an error if the content of the <code>xsl:pi</code> contains
+the string <code>?></code>. An XSL processor may signal the error; if
+it does not signal the error, it must recover by inserting a space
+after any occurrence of <code>?</code> that is followed by another
+<code>></code>.</p>
+
+</div3>
+
+<div3>
+<head>Creating Comments</head>
+
+<p>The <code>xsl:comment</code> element is instantiated to create a
+comment node in the result tree. The content of the
+<code>xsl:comment</code> element is a template for the value of
+the comment node.</p>
+
+<p>For example, this</p>
+
+<eg><![CDATA[<xsl:comment>This file is automatically generated. Do not edit!</xsl:comment>]]></eg>
+
+<p>would create the comment</p>
+
+<eg><![CDATA[<!--This file is automatically generated. Do not edit!-->]]></eg>
+
+<p>It is an error if instantiating the content of
+<code>xsl:comment</code> creates anything other than characters. An
+XSL processor may signal the error; if it does not signal the error,
+it must recover by ignoring the offending nodes together with their
+content.</p>
+
+<p>It is an error if the content of the <code>xsl:comment</code>
+contains the string <code>--</code>. An XSL processor may signal the
+error; if it does not signal the error, it must recover by inserting a
+space after any occurrence of <code>-</code> that is followed by
+another <code>-</code>.</p>
+
+</div3>
+
+<div3>
+<head id="children">Processing with Template Rules</head>
+
+<p>This example creates a block for a <code>chapter</code>
+element and then processes its immediate children.</p>
+
+<eg><![CDATA[<xsl:template match="chapter">
+ <fo:block>
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>]]></eg>
+
+<p>In the absence of a <code>select</code> attribute, the
+<code>xsl:apply-templates</code> instruction processes all of the
+children of the current node, including text nodes. However, text
+nodes that have been stripped as specified in <specref ref="strip"/>
+will not be processed.</p>
+
+<ednote><edtext>There is no WG consensus on the use
+xsl:apply-templates without a select attribute to process all children
+of a node.</edtext></ednote>
+
+<p>A <code>select</code> attribute can be used to process nodes
+selected by a pattern instead of all children. The value of the
+<code>select</code> attribute is a <termref
+def="dt-select-pattern">select pattern</termref>. The following example processes all of
+the <code>author</code> children of the <code>author-group</code>:</p>
+
+<eg><![CDATA[<xsl:template match="author-group">
+ <fo:sequence>
+ <xsl:apply-templates select="author"/>
+ </fo:sequence>
+</xsl:template>]]></eg>
+
+<p>The pattern controls the depth at which matches occur. The
+following example processes all of the <code>first-name</code>s of the
+<code>author</code>s that are direct children of
+<code>author-group</code>:</p>
+
+<eg><![CDATA[<xsl:template match="author-group">
+ <fo:sequence>
+ <xsl:apply-templates select="author/first-name"/>
+ </fo:sequence>
+</xsl:template>]]></eg>
+
+<p><code>//</code> can be used in the pattern to allow the matches to
+occur at arbitrary depths.</p>
+
+<p>This example processes all of the <code>heading</code> elements
+contained in the <code>book</code> element.</p>
+
+<eg><![CDATA[<xsl:template match="book">
+ <fo:block>
+ <xsl:apply-templates select=".//heading"/>
+ </fo:block>
+</xsl:template>]]></eg>
+
+<p>An <nt def="NT-AncestorExpr">AncestorExpr</nt> in the pattern
+allows the processing of elements that are not descendants of the
+current node. This example finds an employee's department and then
+processes the <code>group</code> children of the
+<code>department</code>.</p>
+
+<eg><![CDATA[<xsl:template match="employee">
+ <fo:block>
+ Employee <xsl:apply-templates select="name"/> belongs to group
+ <xsl:apply-templates select="ancestor(department)/group"/>
+ </fo:block>
+</xsl:template>]]></eg>
+
+<p>This example assumes that a <code>department</code> element
+contains <code>group</code> and <code>employee</code> elements (at
+some level). When processing the <code>employee</code> elements, the
+<nt def="NT-AncestorExpr">AncestorExpr</nt> in the pattern allows
+navigation upward to the <code>department</code> element in order to
+extract the information about the group to which the employee
+belongs.</p>
+
+<p>An <nt def="NT-IdExpr">IdExpr</nt> allows processing of
+elements with a specific ID. For example, this template rule applies
+to elements with the ID <code>cfo</code>; the second
+<code>xsl:apply-templates</code> element processes the
+<code>name</code> child of the element with ID <code>ceo</code>:</p>
+
+<eg><![CDATA[<xsl:template match="id(cfo)">
+ <xsl:apply-templates select="name"/> reports to <xsl:apply-templates select="id(ceo)/name"/>
+</xsl:template>]]></eg>
+
+<p>Multiple <code>xsl:apply-templates</code> elements can be used within a
+single template to do simple reordering. The following example
+creates two HTML tables. The first table is filled with domestic sales
+while the second table is filled with foreign sales.</p>
+
+<eg><![CDATA[<xsl:template match="product">
+ <TABLE>
+ <xsl:apply-templates select="sales/domestic"/>
+ </TABLE>
+ <TABLE>
+ <xsl:apply-templates select="sales/foreign"/>
+ </TABLE>
+</xsl:template>]]></eg>
+
+<note>
+
+<p>It is possible for there to be two matching descendants where one
+is a descendant of the other. This case is not treated specially:
+both descendants will be processed as usual. For example, given a
+source document</p>
+
+<eg><![CDATA[<doc><div><div></div></div></doc>]]></eg>
+
+<p>the rule</p>
+
+<eg><![CDATA[<xsl:template match="doc">
+ <xsl:apply-templates select=".//div"/>
+</xsl:template>]]></eg>
+
+<p>will process both the outer <code>div</code> and inner <code>div</code>
+elements.</p>
+
+</note>
+
+<p>Use of select patterns in <code>xsl:apply-templates</code> can lead
+to infinite loops. It is an error if, during the invocation of a rule
+for an element, that same rule is invoked again for that element. An
+XSL processor may signal the error; if it does not signal the error,
+it must recover by creating an empty result tree structure for the
+nested invocation.</p>
+
+<issue id="issue-select-function"><p>What mechanisms should be
+provided for selecting elements for processing? For example, how can
+elements specified indirectly be handled? Suppose there's an
+<code>xref</code> element with a <code>ref</code> attribute that
+specifies the ID of a <code>div</code> element. The template
+for <code>xref</code> needs to select <code>title</code> child of the
+<code>div</code> element referenced by the <code>ref</code> attribute.
+Should it be possible to select elements in other XML
+documents?</p></issue>
+
+</div3>
+
+<div3>
+
+<head>Direct Processing</head>
+
+<p>When the result has a known regular structure, it is useful to be
+able to specify directly the template for selected elements.
+The <code>xsl:for-each</code> element contains a template which
+is instantiated for each element selected by the pattern specified by
+the <code>select</code> attribute.</p>
+
+<ednote><edtext>Make it clear that it changes the current
+node.</edtext></ednote>
+
+<p>For example, given an XML document with this structure</p>
+
+<eg><![CDATA[<customers>
+ <customer>
+ <name>...</name>
+ <order>...</order>
+ <order>...</order>
+ </customer>
+ <customer>
+ <name>...</name>
+ <order>...</order>
+ <order>...</order>
+ </customer>
+</customers>]]></eg>
+
+<p>the following would create an HTML document containing a table with
+a row for each <code>customer</code> element</p>
+
+<eg><![CDATA[<xsl:template match="/">
+ <HTML>
+ <HEAD>
+ <TITLE>Customers</TITLE>
+ </HEAD>
+ <BODY>
+ <TABLE>
+ <TBODY>
+ <xsl:for-each select="customers/customer">
+ <TR>
+ <TH>
+ <xsl:apply-templates select="name"/>
+ </TH>
+ <xsl:for-each select="order">
+ <TD>
+ <xsl:apply-templates/>
+ </TD>
+ </xsl:for-each>
+ </TR>
+ </xsl:for-each>
+ </TBODY>
+ </TABLE>
+ </BODY>
+ </HTML>
+</xsl:template>]]></eg>
+
+<p>As with <code>xsl:apply-templates</code> the pattern is a <termref
+def="dt-select-pattern">select pattern</termref>. The
+<code>select</code> attribute is required.</p>
+
+</div3>
+
+<div3>
+<head>Processing Modes</head>
+
+<p>Processing modes allow an element to processed multiple times, each
+time producing a different result.</p>
+
+<p>Both <code>xsl:template</code> and <code>xsl:apply-templates</code>
+have an optional <code>mode</code> attribute whose value is a name.
+If an <code>xsl:apply-templates</code> element has a <code>mode</code>
+attribute, then it applies only those template rules from
+<code>xsl:template</code> elements that have a <code>mode</code>
+attribute with the same value; if an <code>xsl:apply-templates</code>
+element does not have a <code>mode</code> attribute, then it applies
+only those template rules from <code>xsl:template</code> elements that
+do not have a a <code>mode</code> attribute.</p>
+
+<p>If there is no matching template, then the built-in template rule
+is applied, even if a <code>mode</code> attribute was specified in
+<code>xsl:apply-templates</code>.</p>
+
+<ednote><edtext>Add some examples.</edtext></ednote>
+
+</div3>
+
+<div3>
+<head>Sorting</head>
+
+<p>Sorting is specified by adding <code>xsl:sort</code> elements as
+children of <code>xsl:apply-templates</code> or
+<code>xsl:for-each</code>. The first <code>xsl:sort</code> child
+specifies the primary sort key, the second <code>xsl:sort</code> child
+specifies the secondary sort key and so on. When
+<code>xsl:apply-templates</code> or <code>xsl:for-each</code> has one
+or more <code>xsl:sort</code> children, then instead of processing the
+selected elements in document order, it sorts the elements according
+to the specified sort keys and then processes them in sorted order.
+When used in <code>xsl:for-each</code>, <code>xsl:sort</code> elements
+must occur first.</p>
+
+<p><code>xsl:sort</code> has a <code>select</code> attribute whose
+value is a <termref def="dt-select-pattern">select pattern</termref>.
+For each node to be processed, the select pattern is evaluated with
+that node as the current node. The value of the first selected node is
+used as the sort key for that node. The default value of the code
+<code>select</code> attribute is <code>.</code> (which addresses the
+current element).</p>
+
+<p>This string serves as a sort key for the node. The following
+optional attributes on <code>xsl:sort</code> control how the list of
+sort keys are sorted:</p>
+
+<ulist>
+
+<item><p><code>order</code> specifies whether the strings should be
+sorted in ascending or descending order; <code>ascending</code>
+specifies ascending order; <code>descending</code> specifies
+descending order; the default is <code>ascending</code></p></item>
+
+<item><p><code>lang</code> specifies the language of the sort keys; it
+has the same range of values as <code>xml:lang</code><bibref
+ref="XML"/>; if no <code>lang</code> value is specified, the
+language should be determined from the system environment</p></item>
+
+<item><p><code>data-type</code> specifies the data type of the
+strings; the following values are allowed</p>
+
+<ulist>
+
+<item><p><code>text</code> specifies that the sort keys should be
+sorted lexicograhically in the culturally correct manner for the
+language specified by <code>lang</code></p></item>
+
+<item><p><code>number</code> specifies that the sort keys should be
+converted to numbers and then sorted according to the numeric
+value; the value specified by <code>lang</code> can be used
+to assist in the conversion to numbers</p></item>
+
+</ulist>
+
+<p>The default value is <code>text</code>.</p>
+
+<ednote><edtext>We plan to leverage the work on XML schemas to define
+further values in the future.</edtext></ednote>
+
+</item>
+
+<item><p><code>case-order</code> has the value
+<code>upper-first</code> or <code>lower-first</code>; this applies
+when <code>data-type="text"</code>, and specifies that upper-case
+characters should sort before lower-case letters or vice-versa
+respectively. For example, if <code>lang="en"</code> then <code>A a B
+b</code> are sorted with <code>case-order="upper-first"</code> and
+<code>a A b B</code> are sorted with
+<code>case-order="lower-first"</code>. The default value is language
+dependent.</p></item>
+
+</ulist>
+
+<ednote><edtext>We plan also to add an attribute whose value is a
+label identifying the sorting scheme, to be specified by the I18N
+WG.</edtext></ednote>
+
+<p>The values of all of the above attributes are interpreted as
+<termref def="dt-attribute-value-template">attribute value
+templates</termref>.</p>
+
+<note><p>It is recommended that implementors consult <bibref
+ref="UNICODE-TR10"/> for information on internationalized
+sorting.</p></note>
+
+<p>The sort must be stable: in the sorted list of nodes, any sublist
+that has sort keys that all compare equal must be in document
+order.</p>
+
+<p>For example, suppose an employee database has the form</p>
+
+<eg><![CDATA[<employees>
+ <employee>
+ <name>
+ <first>James</first>
+ <last>Clark</last>
+ </name>
+ ...
+ </employee>
+</employees>
+]]></eg>
+
+<p>Then a list of employees sorted by name could be generated
+using:</p>
+
+<eg><![CDATA[<xsl:template match="employees">
+ <ul>
+ <xsl:apply-templates select="employee">
+ <xsl:sort select="name/last"/>
+ <xsl:sort select="name/first"/>
+ </xsl:apply-templates>
+ </ul>
+</xsl:template>
+
+<xsl:template match="employee">
+ <li>
+ <xsl:value-of select="name/first"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="name/last"/>
+ </li>
+</xsl:template>]]></eg>
+
+</div3>
+
+<div3>
+<head>Numbering</head>
+
+<div4>
+<head>Numbering in the Source Tree</head>
+
+<p>The <code>xsl:number</code> element does numbering based on the
+position of the current node in the source tree.</p>
+
+<p>The <code>xsl:number</code> element can have the following
+attributes:</p>
+
+<ulist>
+
+<item><p>The <code>level</code> attribute specifies what levels of the
+source tree should be considered; it has the values
+<code>single</code>, <code>multi</code> or <code>any</code>. The
+default is <code>single</code>.</p></item>
+
+<item><p>The <code>count</code> attribute is a <termref
+def="dt-match-pattern">match pattern</termref> that specifies what
+elements should be counted at those levels. The <code>count</code>
+attribute defaults to the element type name of the current
+node.</p></item>
+
+<item><p>The <code>from</code> attribute is a <termref
+def="dt-match-pattern">match pattern</termref> that specifies where
+counting starts from.</p></item>
+
+</ulist>
+
+<p>In addition the <code>xsl:number</code> element has the attributes
+specified in <specref ref="convert"/> for number to string
+conversion.</p>
+
+<p>The <code>xsl:number</code> element first constructs a list of
+positive integers using the <code>level</code>, <code>count</code> and
+<code>from</code> attributes:</p>
+
+<ulist>
+
+<item><p>When <code>level="single"</code>, it goes up to the nearest
+ancestor (including the current node as its own ancestor) that
+matches the <code>count</code> pattern, and constructs a list of length one
+containing one plus the number of preceding siblings of that ancestor
+that match the <code>count</code> pattern. If there is no such
+ancestor, it constructs an empty list. If the <code>from</code>
+attribute is specified, then the only ancestors that are searched are
+those that are descendants of the nearest ancestor that matches the
+<code>from</code> pattern.</p></item>
+
+<item><p>When <code>level="multi"</code>, it constructs a list of all
+ancestors of the current node in document order followed by the
+element itself; it then selects from the list those elements that
+match the <code>count</code> pattern; it then maps each element of the
+list to one plus the number of preceding siblings of that element that
+match the <code>count</code> pattern. If the <code>from</code>
+attribute is specified, then the only ancestors that are searched are
+those that are descendants of the nearest ancestor that matches the
+<code>from</code> pattern.</p></item>
+
+<item><p>When <code>level="any"</code>, it constructs a list of length
+one containing one plus the number of elements at any level of the
+document that start before this node and that match the
+<code>count</code> pattern. If the <code>from</code> attribute is
+specified, then only elements after the first element before this
+element that match the <code>from</code> pattern are
+considered.</p></item>
+
+</ulist>
+
+<p>The list of numbers is then converted into a string using the
+attributes specified in <specref ref="convert"/>; when used with
+<code>xsl:number</code> the value of each of these attributes is
+interpreted as an <termref def="dt-attribute-value-template">attribute
+value template</termref>. After conversion, the resulting string is
+inserted in the result tree.</p>
+
+<ednote><edtext>Allowing them to be attribute value templates isn't
+consistent with the current DTD: the declared values would all have to
+be CDATA, and we couldn't use xml:lang because the XML spec doesn't
+allow the value to be expressed as a template.</edtext></ednote>
+
+<p>The following would number the items in an ordered list:</p>
+
+<eg><![CDATA[<xsl:template match="ol/item">
+ <fo:block>
+ <xsl:number/><xsl:text>. </xsl:text><xsl:apply-templates/>
+ </fo:block>
+<xsl:template>]]></eg>
+
+<p>The following two rules would number <code>title</code> elements.
+This is intended for a document that contains a sequence of chapters
+followed by a sequence of appendices, where both chapters and
+appendices contain sections which in turn contain subsections.
+Chapters are numbered 1, 2, 3; appendices are numbered A, B, C;
+sections in chapters are numbered 1.1, 1.2, 1.3; sections in
+appendices are numbered A.1, A.2, A.3.</p>
+
+<eg><![CDATA[<xsl:template match="title">
+ <fo:block>
+ <xsl:number level="multi"
+ count="chapter|section|subsection"
+ format="1.1. "/>
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>
+
+<xsl:template match="appendix//title" priority="1">
+ <fo:block>
+ <xsl:number level="multi"
+ count="appendix|section|subsection"
+ format="A.1. "/>
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>]]></eg>
+
+<p>The following example numbers notes sequentially within a
+chapter:</p>
+
+<eg><![CDATA[<xsl:template match="note">
+ <fo:block>
+ <xsl:number level="any" from="chapter" format="(1) "/>
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>]]></eg>
+
+<p>The following example would number <code>H4</code> elements in HTML
+with a three-part label:</p>
+
+<eg><![CDATA[<xsl:template match="H4">
+ <fo:block>
+ <xsl:number level="any" from="H1" count="H2"/>
+ <xsl:text>.</xsl:text>
+ <xsl:number level="any" from="H2" count="H3"/>
+ <xsl:text>.</xsl:text>
+ <xsl:number level="any" from="H3" count="H4"/>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>]]></eg>
+
+</div4>
+
+<div4>
+<head>Numbering in the Result Tree</head>
+
+<p>The root node of the result and each result element has a set of
+named counters (a mapping from names to integers).</p>
+
+<p>Counter values are inserted using <code>xsl:counter</code> and
+<code>xsl:counters</code> elements. The name of the counter is
+specified with the <code>name</code> attribute.
+<code>xsl:counter</code> first constructs a list of length one
+containing the value of the named counter from the nearest ancestor in
+the result tree that has a counter with the specified name;
+<code>xsl:counters</code> first constructs a list containing, for each
+ancestor in the result tree that has a counter with the specified
+name, the value of named counter from that ancestor.
+<code>xsl:counter</code> and <code>xsl:counters</code> then convert
+the list of numbers into a string using the attributes specified in
+<specref ref="convert"/>; when used with <code>xsl:counter</code> and
+<code>xsl:counters</code> the value of each of these attributes is
+interpreted as an <termref def="dt-attribute-value-template">attribute
+value template</termref>.</p>
+
+<p>Counters are incremented using the
+<code>xsl:counter-increment</code> element. The <code>name</code>
+attribute specifies the name of the counter to be incremented. It
+finds the nearest ancestor in the result tree that has a counter with
+the specified name and increments that; if there is no such ancestor,
+it adds a counter with a value of zero to the document root and then
+increments it. The counter is incremented by 1 by default, but this
+can be changed using the <code>amount</code> attribute.</p>
+
+<p>The <code>xsl:counter-reset</code> element sets the value of a
+counter in the current named counter set. The current named counter
+set is the set of named counters of the containing element in the
+result tree or of the document root if there is no containing element.
+If the current named counter set doesn't contain a counter of that
+name, a counter is added to it, otherwise the existing value is
+changed. The name of the counter to be set is specified by the
+<code>name</code> attribute. The value to set it to is specified by
+the <code>value</code> attribute; this defaults to 0.</p>
+
+<p>The <code>xsl:counter-scope</code> element is a phantom result
+element: it behaves just like a normal result element for the purposes
+of result numbering in that it is considered part of the result tree
+and has a set of named counters, but doesn't actually create a result
+element. This is for when the result tree doesn't have enough
+structure for counting.</p>
+
+<note><p>The numbering may be performed in the tree construction
+process or may be left for the formatting process.</p></note>
+
+<note><p>These facilities for result tree numbering are based on the
+facilities for automatic numbering in <bibref ref="CSS2"/>.</p></note>
+
+<p>The following example would number notes sequentially throughout a
+document:</p>
+
+<eg><![CDATA[<xsl:template match="note">
+ <xsl:text> (Note </xsl:text>
+ <xsl:counter-increment name="note"/>
+ <xsl:counter name="note"/>
+ <xsl:text>).</xsl:text>
+</xsl:template>]]></eg>
+
+<p>The following would turn ordered lists into definition lists:</p>
+
+<eg><![CDATA[<xsl:template match="OL">
+ <dl>
+ <xsl:counter-reset name="li"/>
+ <xsl:apply-templates/>
+ </dl>
+</xsl:template>
+
+<xsl:template match="LI">
+ <xsl:counter-increment name="li"/>
+ <dt><xsl:counter name="li"/></dt>
+ <dd><xsl:apply-templates/></dd>
+</xsl:template>]]></eg>
+
+<p>The following would do HTML style numbering:</p>
+
+<eg><![CDATA[<xsl:template match="h2">
+ <xsl:counter-increment name="h2"/>
+ <p>
+ <xsl:counter name="h2"/>
+ <xsl:text>. </xsl:text>
+ <xsl:apply-templates/>
+ </p>
+ <xsl:counter-reset name="h3"/>
+</xsl:template>
+
+<xsl:template match="h3">
+ <xsl:counter-increment name="h3"/>
+ <p>
+ <xsl:counter name="h2"/>
+ <xsl:text>.</xsl:text>
+ <xsl:counter name="h3"/>
+ <xsl:text>. </xsl:text>
+ <xsl:apply-templates/>
+ </p>
+ <xsl:counter-reset name="h4"/>
+</xsl:template>
+
+<xsl:template match="h4">
+ <xsl:counter-increment name="h4"/>
+ <p>
+ <xsl:counter name="h2"/>
+ <xsl:text>.</xsl:text>
+ <xsl:counter name="h3"/>
+ <xsl:text>.</xsl:text>
+ <xsl:counter name="h4"/>
+ <xsl:text>.</xsl:text>
+ <xsl:apply-templates/>
+ </p>
+</xsl:template>]]></eg>
+
+<p>The following would deal with recursive divs each with a title child:</p>
+
+<eg><![CDATA[<xsl:template match="div">
+ <div>
+ <xsl:apply-templates/>
+ </div>
+</xsl:template>
+
+<xsl:template match="title">
+ <p>
+ <xsl:counter-increment name="div"/>
+ <xsl:counters name="div" format="1.1. "/>
+ <xsl:apply-templates/>
+ </p>
+ <xsl:counter-reset name="div"/>
+</xsl:template>]]></eg>
+
+</div4>
+
+<div4 id="convert">
+<head>Number to String Conversion Attributes</head>
+
+<p>The following attributes are used to control conversion of a list
+of numbers into a string. The numbers are integers greater than
+0. The attributes are all optional.</p>
+
+<p>The main attribute is <code>format</code>. The default value for
+the <code>format</code> attribute is <code>1</code>. The
+<code>format</code> attribute is split into a sequence of tokens where
+each token is a maximal sequence of alphanumeric characters or a
+maximal sequence of non-alphanumeric characters. Alphanumeric means
+any character that has a Unicode category of Nd, Nl, No, Lu, Ll, Lt,
+Lm or Lo. The alphanumeric tokens (format tokens) specify the format
+to be used for each number in the list. If the first token is a
+non-alphanumeric token, then the constructed string will start with
+that token; if the last token is non-alphanumeric token, then the
+constructed string will end with that token. Non-alphanumeric tokens
+that occur between two format tokens are separator tokens that are
+used to join numbers in the list. The n-th format token will be used
+to format the n-th number in the list. If there are more numbers than
+format tokens, then the last format token will be used to format
+remaining numbers. If there are no format tokens, then a format token
+of <code>1</code> is used to format all numbers. The format token
+specifies the string to be used to represent the number 1. Each
+number after the first will be separated from the preceding number by
+the separator token preceding the format token used to format that
+number, or, if there are no separator tokens, then by
+<code>.</code>.</p>
+
+<p>Format tokens are a superset of the allowed values for the
+<code>type</code> attribute for the <code>OL</code> element in HTML
+4.0 and are interpreted as follows:</p>
+
+<ulist>
+
+<item><p>Any token where the last character has a decimal digit value
+of 1 (as specified in the Unicode 2.0 character property database),
+and the Unicode value of preceding characters is one less than the
+Unicode value of the last character. This generates a decimal
+representation of the number where each number is at least as long as
+the format token. Thus a format token <code>1</code> generates the
+sequence <code>1 2 ... 10 11 12 ...</code>, and a format token
+<code>01</code> generates the sequence <code>01 02 ... 09 10 11 12
+... 99 100 101</code>.</p></item>
+
+<item><p>A format token <code>A</code> generates the sequence <code>A
+B C ... Z AA AB AC...</code>.</p></item>
+
+<item><p>A format token <code>a</code> generates the sequence <code>a
+b c ... z aa ab ac...</code>.</p></item>
+
+<item><p>A format token <code>i</code> generates the sequence <code>i
+ii iii iv v vi vii vii ix x ...</code>.</p></item>
+
+<item><p>A format token <code>I</code> generates the sequence <code>I
+II III IV V VI VII VII IX X ...</code>.</p></item>
+
+<item><p>Any other format token indicates a numbering sequence that
+starts with that token. If an implementation does not support a
+numbering system that starts with that token, it must use a format
+token of <code>1</code>.</p></item>
+
+</ulist>
+
+<p>When numbering with an alphabetic sequence, the
+<code>xml:lang</code> attribute specifies which language's alphabet is
+to be used.</p>
+
+<note><p>This can be considered as specifying the language of the
+value of the <code>format</code> attribute and hence is consistent
+with the semantics of <code>xml:lang</code>.</p></note>
+
+<p>The <code>letter-value</code> attribute disambiguates between
+numbering schemes that use letters. In many languages there are two
+commonly used numbering schemes that use letters. One numbering
+scheme assigns numeric values to letters in alphabetic sequence, and
+the other assigns numeric values to each letter in some other manner.
+In English, these would correspond to the numbering sequences
+specified by the format tokens <code>a</code> and <code>i</code>. In
+some languages the first member of each sequence is the same, and so
+the format token alone would be ambiguous. A value of
+<code>alphabetic</code> specifies the alphabetic sequence; a value of
+<code>other</code> specifies the other sequence.</p>
+
+<p>The <code>digit-group-sep</code> attribute gives the separator
+between groups of digits, and the optional
+<code>n-digits-per-group</code> specifies the number of digits per
+group. For example, <code>digit-group-sep=","</code> and
+<code>n-digits-per-group="3"</code> would produce numbers of the form
+<code>1,000,000</code>.</p>
+
+<p>The <code>sequence-src</code> attribute gives the URI of a text
+resource that contains a whitespace separated list of the members of
+the numbering sequence.</p>
+
+<ednote><edtext>Specify what should happen when the sequence runs
+out.</edtext></ednote>
+
+<p>Here are some examples of conversion specifications:</p>
+
+<ulist>
+
+<item><p><code>format="&amp;#x30A2;"</code> specifies Katakana
+numbering</p></item>
+
+<item><p><code>format="&amp;#x30A4;"</code> specifies Katakana
+numbering in the <quote>iroha</quote> order</p></item>
+
+<item><p><code>format="&amp;#x0E51;"</code> specifies numbering with
+Thai digits</p></item>
+
+<item><p><code>format="&amp;#x05D0;" letter-value="other"</code>
+specifies <quote>traditional</quote> Hebrew numbering</p></item>
+
+<item><p><code>format="&amp;#x10D0;" letter-value="other"</code>
+specifies Georgian numbering</p></item>
+
+<item><p><code>format="&amp;#x03B1;" letter-value="other"</code>
+specifies <quote>classical</quote> Greek numbering</p></item>
+
+<item><p><code>format="&amp;#x0430;" letter-value="other"</code>
+specifies Old Slavic numbering</p></item>
+
+</ulist>
+
+</div4>
+
+</div3>
+
+<div3>
+<head>Conditionals within a Template</head>
+
+<p>There are two instructions in XSL which support conditional
+processing in a template: <code>xsl:if</code> and
+<code>xsl:choose</code>. The <code>xsl:if</code> instruction provides
+simple if-then conditionality; the <code>xsl:choose</code> instruction
+supports selection of one choice when there are several
+possibilities.</p>
+
+<div4>
+<head>Conditional Processing with <code>xsl:if</code></head>
+
+<p>The <code>xsl:if</code> element has a single attribute,
+<code>test</code> which specifies a <termref
+def="dt-select-pattern">select pattern</termref>. The content is a
+template. If the pattern selects a non-empty list of elements,
+then the content is instantiated; otherwise nothing is created. In
+the following example, the names in a group of names are formatted as
+a comma separated list:</p>
+
+<eg><![CDATA[<xsl:template match="namelist/name">
+ <xsl:apply-templates/>
+ <xsl:if test=".[not(last-of-type())]">, </xsl:if>
+</xsl:template>]]></eg>
+
+</div4>
+
+
+<div4>
+<head>Conditional Processing with <code>xsl:choose</code></head>
+
+<p>The <code>xsl:choose</code> element selects one among a number of
+possible alternatives. It consists of a series of
+<code>xsl:when</code> elements followed by an optional
+<code>xsl:otherwise</code> element. Each <code>xsl:when</code>
+element has a single attribute, <code>test</code>, which specifies a
+<termref def="dt-select-pattern">select pattern</termref>; the test is
+treated as true if the pattern selects a non-empty list of elements.
+The content of the <code>xsl:when</code> and
+<code>xsl:otherwise</code> elements is a template. When an
+<code>xsl:choose</code> element is processed, each of the
+<code>xsl:when</code> elements is tested in turn. The content of the
+first, and only the first, <code>xsl:when</code> element whose test is
+true is instantiated. If no <code>xsl:when</code> is true, the
+content of the <code>xsl:otherwise</code> element is instantiated. If
+no <code>xsl:when</code> element is true, and no
+<code>xsl:otherwise</code> element is present, nothing is created.</p>
+
+<p>The following example enumerates items in an ordered list using
+arabic numerals, letters, or roman numerals depending on the depth to
+which the ordered lists are nested.</p>
+
+<eg><![CDATA[<xsl:template match="orderedlist/listitem">
+ <fo:list-item indent-start='2pi'>
+ <fo:list-item-label>
+ <xsl:choose>
+ <xsl:when test='ancestor(orderedlist/orderedlist)'>
+ <xsl:number format="i"/>
+ </xsl:when>
+ <xsl:when test='ancestor(orderedlist)'>
+ <xsl:number format="a"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:number format="1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>. </xsl:text>
+ </fo:list-item-label>
+ <fo:list-item-body>
+ <xsl:apply-templates/>
+ </fo:list-item-body>
+ </fo:list-item>
+</xsl:template>]]></eg>
+</div4>
+</div3>
+
+<div3>
+<head>Copying</head>
+
+<p>The <code>xsl:copy</code> element provides an easy way of copying
+the current node. The <code>xsl:copy</code> element is replaced by a
+copy of the current node. Only the children of the node are not
+automatically copied. Everything else about the current node,
+including the attribute nodes and the namespace nodes, are
+automatically copied. The content of the <code>xsl:copy</code>
+element is a template for the children of the created node; the
+content is not used for nodes of types that do not have children
+(attributes, text, comments and processing instructions).</p>
+
+<p>The root node is treated specially because the root node of the
+result tree is created implicitly. When the current node is the root
+node, <code>xsl:copy</code> will not create a root node, but will just
+use the content template.</p>
+
+<p>For example, the identity transformation can be written using
+<code>xsl:copy</code>:</p>
+
+<eg><![CDATA[<xsl:template match="*|comment()|pi()">
+ <xsl:copy>
+ <xsl:apply-templates/>
+ </xsl:copy>
+</xsl:template>]]></eg>
+
+<issue id="issue-copy-attributes"><p>Should there be some way for
+<code>xsl:copy</code> to control the copying of
+attributes?</p></issue>
+
+</div3>
+
+
+<div3 id="stringexpr">
+<head>Computing Generated Text</head>
+
+<p>Within a template, the <code>xsl:value-of</code> element can
+be used to compute generated text, for example by extracting text from
+the source tree or by inserting the value of a string constant. The
+<code>xsl:value-of</code> element does this with a string expression
+that is specified as the value of the <code>select</code> attribute.
+String expressions can also be used inside attribute values of literal
+result elements by enclosing the string expression in curly brace
+(<code>{}</code>).</p>
+
+<div4>
+<head>String Expressions</head>
+
+<scrap>
+<head>String Expressions</head>
+<prod id="NT-StringExpr">
+<lhs>StringExpr</lhs>
+<rhs><nt def="NT-SelectExpr">SelectExpr</nt></rhs>
+<rhs>| <nt def="NT-NameExpr">NameExpr</nt></rhs>
+<rhs>| <nt def="NT-ConstantRef">ConstantRef</nt></rhs>
+<rhs>| <nt def="NT-MacroArgRef">MacroArgRef</nt></rhs>
+</prod>
+</scrap>
+
+<p>The value of a string expression that is a pattern is the value of
+the first node selected by the pattern. The value of each kind of
+node is described in <specref ref="data-model"/>. If no nodes are
+selected by the pattern, then the value is the empty string. The
+pattern is a <termref def="dt-select-pattern">select
+pattern</termref>.</p>
+
+<issue id="issue-resolve-expr"><p>Do we need a
+<code>resolve(pattern)</code> string expression that treats the
+characters as a relative URI and turns it into an absolute URI using
+the base URI of the addressed node?</p></issue>
+
+<scrap>
+<head>Name Expression</head>
+<prod id="NT-NameExpr">
+<lhs>NameExpr</lhs>
+<rhs>'name' '(' <nt def="NT-SelectExpr">SelectExpr</nt> ')'</rhs>
+</prod>
+</scrap>
+
+<p>The value of a <nt def="NT-NameExpr">NameExpr</nt> is the expanded
+name of the first node selected by the <nt
+def="NT-SelectExpr">SelectExpr</nt>. If no nodes are selected or the first
+node does not have a name, then the value is the empty string. If the
+expanded name has a null URI, then the value is just the local
+name. If the expanded name has a non-null URI, the the value is the
+URI followed by the character <code>#</code> followed by the local
+name.</p>
+
+</div4>
+
+<div4>
+<head>Using String Expressions with <code>xsl:value-of</code></head>
+
+<p>The <code>xsl:value-of</code> element is replaced by the value of
+the string expression specified by the <code>select</code> attribute.
+The <code>select</code> attribute is required.</p>
+
+<p>For example, the following creates an HTML paragraph from a
+<code>person</code> element with <code>first-name</code> and
+<code>surname</code> attributes.</p>
+
+<eg><![CDATA[<xsl:template match="person">
+ <P>
+ <xsl:value-of select="@first-name"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@surname"/>
+ </P>
+</xsl:template>]]></eg>
+
+<p>For example, the following creates an HTML paragraph from a
+<code>person</code> element with <code>first-name</code> and
+<code>surname</code> children elements.</p>
+
+<eg><![CDATA[<xsl:template match="person">
+ <P>
+ <xsl:value-of select="first-name"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="surname"/>
+ </P>
+</xsl:template>]]></eg>
+
+<p>The following precedes each <code>procedure</code> element with a
+paragraph containing the security level of the procedure. It assumes
+that the security level that applies to a procedure is determined by a
+<code>security</code> attribute on an ancestor element of the
+procedure. It also assumes that if more than one ancestor has a
+<code>security</code> attribute then the security level is determined
+by the closest such ancestor of the procedure.</p>
+
+<eg><![CDATA[<xsl:template match="procedure">
+ <fo:block>
+ <xsl:value-of select="ancestor(*[@security])/@security"/>
+ </fo:block>
+ <xsl:apply-templates/>
+</xsl:template>]]></eg>
+
+<issue id="issue-inherited-attribute"><p>Unless an element counts as
+one of its own ancestors, using
+<code>ancestor(*[@security])/@security</code>
+won't work to get the inherited value of an attribute. We could
+either say <code>ancestor</code> always includes the current node;
+alternatively we could provide a variant of <code>ancestor</code> that
+does include the current node; alternatively we could provide a select
+pattern of the form
+<code>inherited-attribute('security')</code>.</p></issue>
+
+</div4>
+
+<div4 id="attribute-value-templates">
+<head>Attribute Value Templates</head>
+
+<p><termdef id="dt-attribute-value-template" term="Attribute Value
+Template">In an attribute value that is interpreted as an
+<term>attribute value template</term>, such as an attribute of a
+literal result element, string expressions can be used by surrounding
+the string expression with curly braces (<code>{}</code>)</termdef>.
+The attribute value template is instantiated by replacing the string
+expression together with surrounding curly braces by the value of the
+string expression.</p>
+
+<p>The following example creates an <code>IMG</code> result element
+from a <code>photograph</code> element in the source; the value of the
+<code>SRC</code> attribute of the <code>IMG</code> element is computed
+from the value of the <code>image-dir</code> constant and the content
+of the <code>href</code> child of the <code>photograph</code> element;
+the value of the <code>WIDTH</code> attribute of the <code>IMG</code>
+element is computed from the value of the the <code>width</code>
+attribute of the <code>size</code> child of the
+<code>photograph</code> element:</p>
+
+<eg><![CDATA[<xsl:constant name="image-dir" value="/images"/>
+
+<xsl:template match="photograph">
+<IMG SRC="{constant(image-dir)}/{href}" WIDTH="{size/@width}"/>
+</xsl:template>]]></eg>
+
+<p>With this source</p>
+
+<eg><![CDATA[<photograph>
+ <href>headquarters.jpg</href>
+ <size width="300"/>
+</photograph>]]></eg>
+
+<p>the result would be</p>
+
+<eg><![CDATA[<IMG SRC="/images/headquarters.jpg" WIDTH="300"/>]]></eg>
+
+<p>When an attribute value template is instantiated, a double left or
+right curly brace outside a string expression will be replaced by a
+single curly brace. It is an error if a right curly brace occurs in
+an attribute value template outside a string expression without being
+followed by a second right curly brace; an XSL processor may signal
+the error or recover by treating the right curly brace as if it had
+been doubled. A right curly brace inside an <nt
+def="NT-Literal">Literal</nt> in a string expression is
+not recognized as terminating the string expression.</p>
+
+<p>Curly braces are <emph>not</emph> recognized recursively inside
+string expressions. For example:</p>
+
+<eg role="error"><![CDATA[<a href="#{id({@ref})/title}">]]></eg>
+
+<p>is <emph>not</emph> allowed. Instead use simply:</p>
+
+<eg><![CDATA[<a href="#{id(@ref)/title}">]]></eg>
+
+</div4>
+
+</div3>
+
+<div3>
+<head>String Constants</head>
+
+<p>Global string constants may be defined using a
+<code>constant</code> element. The name attribute specifies
+the name of the constant, and the <code>value</code> attribute
+specified the value.</p>
+
+<p>A stylesheet must not contain more than one definition of a
+constant with the same name and same <termref
+def="dt-important">importance</termref>. A definition of a
+constant will not be used if there is another definition of a constant
+with the same name and higher <termref
+def="dt-important">importance</termref>.</p>
+
+<p>String constants are referenced using a <nt
+def="NT-ConstantRef">ConstantRef</nt> string expression.</p>
+
+<scrap>
+<head>String Constant References</head>
+<prod id="NT-ConstantRef">
+<lhs>ConstantRef</lhs>
+<rhs>'constant' '(' <xnt href="&XMLNames;#NT-NCName">NCName</xnt> ')'</rhs>
+</prod>
+</scrap>
+
+<eg><![CDATA[<xsl:constant name="para-font-size" value="12pt"/>
+
+<xsl:template match="para">
+ <fo:block font-size="{constant(para-font-size)}">
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>
+]]></eg>
+
+<issue id="issue-local-constants"><p>Should there be a way to define
+local constants?</p></issue>
+
+<p>The <code>value</code> attribute is interpreted as an <termref
+def="dt-attribute-value-template">attribute value template</termref>.
+If the value of a constant definition <code>x</code> references a
+constant <code>y</code>, then the value for <code>y</code> must be
+computed before the value of <code>x</code>. It is an error if it is
+impossible to do this for all constant definitions because of
+dependency cycles.</p>
+
+</div3>
+
+<div3>
+<head>Macros</head>
+
+<issue id="issue-macro-name"><p>Should macros be called something
+else?</p></issue>
+
+<p>Parts of templates can also be factored out of similar rules
+into macros for reuse. Macros allow authors to create aggregate
+result fragments and refer to the composite as if it were a single
+object. In this example, a macro is defined for a boxed paragraph
+with the word <quote>Warning!</quote> preceding the contents. The
+macro is referenced from a rule for <code>warning</code> elements.</p>
+
+<eg><![CDATA[<xsl:macro name="warning-para">
+ <fo:block-level-box>
+ <fo:block>
+ <xsl:text>Warning! </xsl:text>
+ <xsl:contents/>
+ </fo:block>
+ </fo:block-level-box>
+</xsl:macro>
+
+<xsl:template match="warning">
+ <xsl:invoke macro="warning-para">
+ <xsl:apply-templates/>
+ </xsl-invoke>
+</xsl:template>]]></eg>
+
+<p>Macros are defined using the <code>macro</code> element. The
+<code>name</code> attribute specifies the name of the macro being
+defined. The content of the <code>macro</code> element is a
+template, called the body of the macro. A macro is invoked
+using the <code>xsl:invoke</code> element; the content of
+<code>xsl:invoke</code> is a template. The name of the macro
+to be invoked is given by the <code>macro</code> attribute. Invoking a
+macro first instantiates the content of <code>xsl:invoke</code>. It
+then instantiates the body of the invoked macro passing it the result tree
+fragment created by the instantiation of the content of
+<code>xsl:invoke</code>; this fragment can be inserted in the body of
+the macro using the <code>xsl:contents</code> element.</p>
+
+<p>Macros allow named arguments to be declared with the
+<code>xsl:macro-arg</code> element; the <code>name</code> attribute
+specifies the argument name, and the optional <code>default</code>
+attribute specifies the default value for the argument. Within the
+body of a macro, macro arguments are referenced using a <nt
+def="NT-MacroArgRef">MacroArgRef</nt> string expression. It is an
+error to refer to a macro argument that has not been declared. An XSL
+processor may signal the error; if it does not signal the error, it
+must recover by using an empty string. Arguments are supplied to a
+macro invocation using the code <code>xsl:arg</code> element; the
+<code>name</code> attribute specifies the argument name, and the
+<code>value</code> attribute specifies the argument value. It is an
+error to supply an argument to a macro invocation if the macro did not
+declare an argument of that name. An XSL processor may signal the
+error; if it does not signal the error, it must recover by ignoring
+the argument. The <code>value</code> attribute of
+<code>xsl:arg</code> and the <code>default</code> attribute of
+<code>xsl:macro-arg</code> are interpreted as <termref
+def="dt-attribute-value-template">attribute value templates</termref>;
+they can contain string expressions in curly braces as with literal
+result elements.</p>
+
+<scrap>
+<head>Macro Argument References</head>
+<prod id="NT-MacroArgRef">
+<lhs>MacroArgRef</lhs>
+<rhs>'arg' '(' <xnt href="&XMLNames;#NT-NCName">NCName</xnt> ')'</rhs>
+</prod>
+</scrap>
+
+<p>This example defines a macro for a <code>numbered-block</code> with
+an argument to control the format of the number.</p>
+
+<eg><![CDATA[<xsl:macro name="numbered-block">
+ <xsl:macro-arg name="format" default="1. "/>
+ <xsl:number format="{arg(format)}"/>
+ <fo:block/>
+ <xsl:contents/>
+ </fo:block>
+</xsl:macro>
+
+<xsl:template match="appendix/title">
+ <xsl:invoke macro="numbered-block">
+ <xsl:arg name="format" value="A. "/>
+ <xsl:apply-templates/>
+ </xsl:invoke>
+</xsl:template>]]></eg>
+
+<p>It is an error if a stylesheet contains more than one definition of
+a macro with the same name and same <termref
+def="dt-important">importance</termref>. An XSL processor may signal
+the error; if it does not signal the error, if must recover by
+choosing from amongst the definitions with highest importance the one
+that occurs last in the stylesheet.</p>
+
+<issue id="issue-macro-arg-syntax"><p>The proposal used the same
+element for declaring macro arguments and for invoking them. Should
+these be separate elements and if so what should they be
+called?</p></issue>
+
+</div3>
+</div2>
+
+<div2>
+<head>Combining Stylesheets</head>
+
+<p>XSL provides two mechanisms to combine stylesheets:</p>
+
+<slist>
+
+<sitem>an import mechanism that allows stylesheets to override each
+other, and</sitem>
+
+<sitem>an inclusion mechanism that allows stylesheets to be textually
+combined.</sitem>
+
+</slist>
+
+<div3 id="import">
+<head>Stylesheet Import</head>
+
+<p>An XSL stylesheet may contain <code>xsl:import</code> elements. All
+the <code>xsl:import</code> elements must occur at the beginning of
+the stylesheet. The <code>xsl:import</code> element has an
+<code>href</code> attribute whose value is the URI of a stylesheet to
+be imported. A relative URI is resolved relative to the base URI of
+the <code>xsl:import</code> element (see <specref
+ref="base-uri"/>).</p>
+
+<eg><![CDATA[<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
+ <xsl:import href="article.xsl"/>
+ <xsl:import href="bigfont.xsl"/>
+ <xsl:attribute-set name="note-style">
+ <xsl:attribute name="font-style">italic</xsl:attribute>
+ </xsl:attribute-set>
+</xsl:stylesheet>]]></eg>
+
+<p><termdef id="dt-important" term="Important">Rules and definitions in
+the importing stylesheet are defined to be more <term>important</term>
+than rules and definitions in any imported stylesheets. Also rules
+and definitions in one imported stylesheet are defined to be more
+<term>important</term> than rules and definitions in previous imported
+stylesheets.</termdef></p>
+
+<p>In general a more important rule or definition takes precedence
+over a less important rule or definition. This is defined in detail
+for each kind of rule and definition.</p>
+
+<issue id="issue-stylesheet-partition"><p>Should there be an XSL
+defined element that can be used to divide a stylesheet into parts,
+each of which is treated as if it were separately imported for
+precedence purposes?</p></issue>
+
+<issue id="issue-import-source"><p>Provide a way for a stylesheet
+to import a stylesheet that is embedded in the document.</p></issue>
+
+<issue id="issue-import-media"><p>Should we provide media-dependent
+imports as in CSS?</p></issue>
+
+<ednote><edtext>Say something about the case where the same stylesheet
+gets imported twice. This should be treated the same as importing a
+stylesheet with the same content but different URIs. What about
+import loops?</edtext></ednote>
+
+<p><code>xsl:apply-templates</code> processes the current node using
+only template rules that were imported into the stylesheet containing
+the current rule; the current node is processed in the current rule's
+mode.</p>
+
+<ednote><edtext>Expand this.</edtext></ednote>
+
+</div3>
+
+<div3>
+<head>Stylesheet Inclusion</head>
+
+<p>An XSL stylesheet may include another XSL stylesheet using an
+<code>xsl:include</code> element. The <code>xsl:include</code> element
+has an <code>href</code> attribute whose value is the URI of a
+stylesheet to be included. A relative URI is resolved relative to the
+base URI of the <code>xsl:include</code> element (see <specref
+ref="base-uri"/>). The <code>xsl:include</code> element can occur as
+the child of the <code>xsl:stylesheet</code> element at any point
+after all <code>xsl:import</code> elements.</p>
+
+<p>The inclusion works at the XML tree level. The resource located by
+the <code>href</code> attribute value is parsed as an XML document,
+and the children of the <code>xsl:stylesheet</code> element in this
+document replace the <code>xsl:include</code> element in the including
+document. Also any <code>xsl:import</code> elements in the included
+document are moved up in the including document to after any existing
+<code>xsl:import</code> elements in the including document. Unlike
+with <code>xsl:import</code>, the fact that rules or definitions are
+included does not affect the way they are processed.</p>
+
+<ednote><edtext>What happens when a stylesheet directly or indirectly
+includes itself?</edtext></ednote>
+
+</div3>
+
+<div3>
+<head>Embedding Stylesheets</head>
+
+<p>Normally an XSL stylesheet is a complete XML document with the
+<code>xsl:stylesheet</code> element as the document element. However an XSL
+stylesheet may also be embedded in another resource. Two forms of
+embedding are possible:</p>
+
+<slist>
+
+<sitem>the XSL stylesheet may be textually embedded in a non-XML
+resource, or</sitem>
+
+<sitem>the <code>xsl:stylesheet</code> element may occur in an XML
+document other than as the document element.</sitem>
+
+</slist>
+
+<p>In the second case, the possibility arises of documents with inline
+style, that is documents that specify their own style. XSL does not
+define a specific mechanism for this. This is because this can be done
+by means of a general purpose mechanism for associating stylesheets
+with documents provided that:</p>
+
+<slist>
+
+<sitem>the mechanism allows a part of a resource to be specified as
+the stylesheet, for example by using a URI with a fragment identifier,
+and</sitem>
+
+<sitem>the mechanism can itself can be embedded in the document, for
+example as a processing instruction.</sitem>
+
+</slist>
+<p>It is not in the scope of XSL to define such a mechanism.</p>
+<note>
+<p>This is because the mechanism should be independent of any one stylesheet
+mechanism.</p>
+</note>
+<p>The xsl:stylesheet element may have an ID attribute that specifies a unique
+identifier.</p>
+
+<note><p>In order for such an attribute to be used with the
+<code>id</code> XPointer location term, it must actually be declared
+in the DTD as being an ID.</p></note>
+
+<p>The following example shows how inline style can be accomplished
+using the <code>xml-stylesheet</code> processing instruction mechanism
+for associating a stylesheet with an XML document. The URI uses an
+XPointer in a fragment identifier to locate the
+<code>xsl:stylesheet</code> element.</p>
+
+<eg><![CDATA[<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="#id(style1)"?>
+<!DOCTYPE doc SYSTEM "doc.dtd">
+<doc>
+<head>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" id="style1">
+<xsl:import href="doc.xsl"/>
+<xsl:template match="id(foo)">
+ <fo:block font-weight="bold"><xsl:apply-templates/></fo:block>
+</xsl:template>
+</xsl:stylesheet>
+</head>
+<body>
+<para id="foo">
+...
+</para>
+</body>
+</doc>
+]]></eg>
+
+<note><p>The <code>type</code> pseudo-attribute in the
+<code>xml-stylesheet</code> processing instruction identifies the
+stylesheet language, not the content type of the resource of which the
+stylesheet is a part.</p></note>
+
+</div3>
+</div2>
+
+<div2>
+<head>Extensibility</head>
+
+<p>This section will describe an extensibility mechanism for the tree
+construction process.</p>
+
+<issue id="issue-construct-extensibility"><p>Should there be some
+extensibility mechanism for the tree construction process? If so, how
+should it work? Should it be language independent?</p></issue>
+
+</div2>
+
+</div1>
+
+&fo;
+
+</body>
+<back>
+<div1>
+<head>DTD for XSL Stylesheets</head>
+
+<p>The following entity can be used to construct a DTD for XSL
+stylesheets that create instances of a particular result DTD. Before
+referencing the entity, the stylesheet DTD must define a
+<code>result-elements</code> parameter entity listing the allowed
+result element types. For example:</p>
+
+<eg><![CDATA[<!ENTITY % result-elements "
+ | fo:sequence
+ | fo:block
+">]]></eg>
+
+<eg><![CDATA[<!ENTITY % instructions "
+ | xsl:apply-templates
+ | xsl:apply-imports
+ | xsl:for-each
+ | xsl:value-of
+ | xsl:number
+ | xsl:counter
+ | xsl:counters
+ | xsl:counter-increment
+ | xsl:counter-reset
+ | xsl:counter-scope
+ | xsl:choose
+ | xsl:if
+ | xsl:contents
+ | xsl:invoke
+ | xsl:text
+ | xsl:pi
+ | xsl:comment
+ | xsl:element
+ | xsl:attribute
+ | xsl:copy
+">
+
+<!ENTITY % template "
+ (#PCDATA
+ %instructions;
+ %result-elements;)*
+">
+
+<!ENTITY % space-att "xml:space (default|preserve) #IMPLIED">
+
+<!ELEMENT xsl:stylesheet
+ (xsl:import*,
+ (xsl:include
+ | xsl:id
+ | xsl:strip-space
+ | xsl:preserve-space
+ | xsl:macro
+ | xsl:attribute-set
+ | xsl:constant
+ | xsl:template)*)
+>
+
+<!ATTLIST xsl:stylesheet
+ result-ns NMTOKEN #IMPLIED
+ default-space (preserve|strip) "preserve"
+ indent-result (yes|no) "no"
+ id ID #IMPLIED
+ xmlns:xsl CDATA #FIXED "http://www.w3.org/TR/WD-xsl"
+ %space-att;
+>
+
+<!-- Used for attribute values that are URIs.-->
+<!ENTITY % URI "CDATA">
+
+<!-- Used for attribute values that are patterns.-->
+<!ENTITY % pattern "CDATA">
+
+<!-- Used for attribute values that are a priority. -->
+<!ENTITY % priority "NMTOKEN">
+
+<!ELEMENT xsl:import EMPTY>
+<!ATTLIST xsl:import href %URI; #REQUIRED>
+
+<!ELEMENT xsl:include EMPTY>
+<!ATTLIST xsl:include href %URI; #REQUIRED>
+
+<!ELEMENT xsl:id EMPTY>
+<!ATTLIST xsl:id
+ attribute NMTOKEN #REQUIRED
+ element NMTOKEN #IMPLIED
+>
+
+<!ELEMENT xsl:strip-space EMPTY>
+<!ATTLIST xsl:strip-space element NMTOKEN #REQUIRED>
+
+<!ELEMENT xsl:preserve-space EMPTY>
+<!ATTLIST xsl:preserve-space element NMTOKEN #REQUIRED>
+
+<!ELEMENT xsl:template %template;>
+<!ATTLIST xsl:template
+ match %pattern; #REQUIRED
+ priority %priority; #IMPLIED
+ mode NMTOKEN #IMPLIED
+ %space-att;
+>
+
+<!ELEMENT xsl:value-of EMPTY>
+<!ATTLIST xsl:value-of select CDATA #IMPLIED>
+
+<!ENTITY % conversion-atts '
+ format CDATA "1"
+ xml:lang NMTOKEN #IMPLIED
+ letter-value (alphabetic|other) #IMPLIED
+ digit-group-sep CDATA #IMPLIED
+ n-digits-per-group NMTOKEN #IMPLIED
+ sequence-src %URI; #IMPLIED
+'>
+
+<!ELEMENT xsl:number EMPTY>
+<!ATTLIST xsl:number
+ level (single|multi|any) "single"
+ count CDATA #IMPLIED
+ from CDATA #IMPLIED
+ %conversion-atts;
+>
+
+<!ELEMENT xsl:counter EMPTY>
+<!ATTLIST xsl:counter
+ name NMTOKEN #REQUIRED
+ %conversion-atts;
+>
+
+<!ELEMENT xsl:counters EMPTY>
+<!ATTLIST xsl:counters
+ name NMTOKEN #REQUIRED
+ %conversion-atts;
+>
+
+<!ELEMENT xsl:counter-increment EMPTY>
+<!ATTLIST xsl:counter-increment
+ name NMTOKEN #REQUIRED
+ amount NMTOKEN #IMPLIED
+>
+
+<!ELEMENT xsl:counter-reset EMPTY>
+<!ATTLIST xsl:counter-reset
+ name NMTOKEN #REQUIRED
+ value NMTOKEN #IMPLIED
+>
+
+<!ELEMENT xsl:counter-scope %template;>
+<!ATTLIST xsl:counter-scope %space-att;>
+
+<!ELEMENT xsl:apply-templates (xsl:sort*)>
+<!ATTLIST xsl:apply-templates
+ select %pattern; #IMPLIED
+ mode NMTOKEN #IMPLIED
+>
+
+<!ELEMENT xsl:apply-imports EMPTY>
+
+<!-- xsl:sort cannot occur after any other elements or
+any non-whitespace character -->
+
+<!ELEMENT xsl:for-each
+ (#PCDATA
+ %instructions;
+ %result-elements;
+ | xsl:sort)*
+>
+
+<!ATTLIST xsl:for-each
+ select %pattern; #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:sort EMPTY>
+<!ATTLIST xsl:sort
+ select %pattern; "."
+ lang CDATA #IMPLIED
+ data-type (text|number) "text"
+ order (ascending|descending) "ascending"
+ case-order (upper-first|lower-first) #IMPLIED
+>
+
+<!ELEMENT xsl:if %template;>
+<!ATTLIST xsl:if
+ test %pattern; #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:choose (xsl:when+, xsl:otherwise?)>
+<!ATTLIST xsl:choose %space-att;>
+
+<!ELEMENT xsl:when %template;>
+<!ATTLIST xsl:when
+ test %pattern; #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:otherwise %template;>
+<!ATTLIST xsl:otherwise %space-att;>
+
+<!ELEMENT xsl:attribute-set (xsl:attribute)*>
+<!ATTLIST xsl:attribute-set
+ name NMTOKEN #REQUIRED
+>
+
+<!ELEMENT xsl:constant EMPTY>
+<!ATTLIST xsl:constant
+ name NMTOKEN #REQUIRED
+ value CDATA #REQUIRED
+>
+
+<!-- xsl:macro-arg cannot occur after any other elements or
+any non-whitespace character -->
+
+<!ELEMENT xsl:macro
+ (#PCDATA
+ %instructions;
+ %result-elements;
+ | xsl:macro-arg)*
+>
+
+<!ATTLIST xsl:macro
+ name NMTOKEN #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:macro-arg EMPTY>
+<!ATTLIST xsl:macro-arg
+ name NMTOKEN #REQUIRED
+ default CDATA #IMPLIED
+>
+
+<!-- This is allowed only within xsl:macro -->
+<!ELEMENT xsl:contents EMPTY>
+
+<!-- xsl:arg cannot occur after any other elements or
+any non-whitespace character -->
+
+<!ELEMENT xsl:invoke
+ (#PCDATA
+ %instructions;
+ %result-elements;
+ | xsl:arg)*
+>
+
+<!ATTLIST xsl:invoke
+ macro NMTOKEN #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:arg EMPTY>
+<!ATTLIST xsl:arg
+ name NMTOKEN #REQUIRED
+ value CDATA #REQUIRED
+>
+
+<!ELEMENT xsl:text (#PCDATA)>
+<!ATTLIST xsl:text %space-att;>
+
+<!ELEMENT xsl:pi %template;>
+<!ATTLIST xsl:pi
+ name CDATA #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:element %template;>
+<!ATTLIST xsl:element
+ name CDATA #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:attribute %template;>
+<!ATTLIST xsl:attribute
+ name CDATA #REQUIRED
+ %space-att;
+>
+
+<!ELEMENT xsl:comment %template;>
+<!ATTLIST xsl:comment %space-att;>
+
+<!ELEMENT xsl:copy %template;>
+<!ATTLIST xsl:copy %space-att;>
+
+]]></eg>
+</div1>
+
+<div1>
+<head>References</head>
+<div2>
+<head>Normative References</head>
+<blist>
+
+<bibl id="XML" key="W3C XML">World Wide Web Consortium. <emph>Extensible
+Markup Language (XML) 1.0.</emph> W3C Recommendation. See <loc
+href="http://www.w3.org/TR/1998/REC-xml-19980210">http://www.w3.org/TR/1998/REC-xml-19980210</loc></bibl>
+
+<bibl id="XMLNAMES" key="W3C XML Names">World Wide Web
+Consortium. <emph>Namespaces in XML.</emph> W3C Working Draft. See
+<loc
+href="http://www.w3.org/TR/WD-xml-names">http://www.w3.org/TR/WD-xml-names</loc></bibl>
+
+</blist>
+</div2>
+<div2>
+<head>Other References</head>
+
+<blist>
+
+<bibl id="CSS2" key="CSS2">World Wide Web Consortium. <emph>Cascading
+Style Sheets, level 2 (CSS2)</emph>. W3C Recommendation. See <loc
+href="http://www.w3.org/TR/1998/REC-CSS2-19980512"
+>http://www.w3.org/TR/1998/REC-CSS2-19980512</loc></bibl>
+
+<bibl id="DSSSL" key="DSSSL">International Organization
+for Standardization, International Electrotechnical Commission.
+<emph>ISO/IEC 10179:1996. Document Style Semantics and Specification
+Language (DSSSL)</emph>. International Standard.</bibl>
+
+<bibl id="UNICODE-TR10" key="UNICODE TR10">Unicode Consortium. <emph>Draft
+Unicode Technical Report #10. Unicode Collation Algorithm</emph>.
+Draft Unicode Technical Report. See <loc
+href="http://www.unicode.org/unicode/reports/tr10/index.html"
+>http://www.unicode.org/unicode/reports/tr10/index.html</loc>.</bibl>
+
+<bibl id="XMLSTYLE" key="W3C XML Stylesheet">World Wide Web
+Consortium. <emph>Associating stylesheets with XML documents.</emph>
+W3C Working Draft. See <loc
+href="http://www.w3.org/TR/WD-xml-stylesheet">http://www.w3.org/TR/WD-xml-stylesheet</loc></bibl>
+
+</blist>
+
+</div2>
+</div1>
+<inform-div1>
+<head>Examples</head>
+<p>The following is a simple but complete stylesheet.</p>
+
+<eg><![CDATA[<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"
+ xmlns:fo="http://www.w3.org/TR/WD-xsl/FO"
+ result-ns="fo"
+ indent-result="yes">
+<xsl:template match='/'>
+ <fo:page-sequence font-family="serif">
+ <fo:simple-page-master name='scrolling'/>
+ <fo:queue queue-name='body'>
+ <xsl:apply-templates/>
+ </fo:queue>
+ </fo:page-sequence>
+</xsl:template>
+
+<xsl:template match="title">
+ <fo:block font-weight="bold">
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>
+
+<xsl:template match="p">
+ <fo:block>
+ <xsl:apply-templates/>
+ </fo:block>
+</xsl:template>
+
+<xsl:template match="emph">
+ <fo:sequence font-style="italic">
+ <xsl:apply-templates/>
+ </fo:sequence>
+</xsl:template>
+
+</xsl:stylesheet>]]></eg>
+
+<p>With the following source document</p>
+
+<eg><![CDATA[<doc>
+<title>An example</title>
+<p>This is a test.</p>
+<p>This is <emph>another</emph> test.</p>
+</doc>]]></eg>
+
+<p>it would produce the following result</p>
+
+<eg><![CDATA[<fo:page-sequence xmlns:fo="http://www.w3.org/TR/WD-xsl/FO"
+ font-family="serif">
+<fo:simple-page-master name="scrolling"/>
+<fo:queue queue-name="body">
+<fo:block font-weight="bold">An example</fo:block>
+<fo:block>This is a test.</fo:block>
+<fo:block>This is <fo:sequence
+ font-style="italic">another</fo:sequence> test.</fo:block>
+</fo:queue>
+</fo:page-sequence>]]></eg>
+
+</inform-div1>
+
+<inform-div1>
+<head>Design Principles</head>
+
+<p>In the design of any language, trade-offs in the solution space are
+necessary. To aid in making these trade-offs the follow design
+principles were used:</p>
+
+<slist>
+<sitem>XSL should support browsing, printing, and interactive editing and
+design tools</sitem>
+<sitem>XSL should be capable of specifying presentations for traditional and
+Web environments</sitem>
+<sitem>XSL should support interaction with structured information, as well
+as presentation of it.</sitem>
+<sitem>XSL should support all kinds of structured information, including both
+data and documents.</sitem>
+<sitem>XSL should support both visual and non-visual presentations.</sitem>
+<sitem>XSL should be a declarative language.</sitem>
+<sitem>XSL should be optimized to provide simple specifications for common
+formatting tasks and not preclude more sophisticated formatting tasks.</sitem>
+<sitem>XSL should provide an extensibility mechanism</sitem>
+<sitem>The number of optional features in XSL should be kept to a minimum.</sitem>
+<sitem>XSL should provide the formatting functionality of <emph>at
+least</emph> DSSSL and CSS</sitem>
+<sitem>XSL should leverage other recommendations and standards, including
+XML, XLL, DOM, HTML and ECMAScript.</sitem>
+<sitem>XSL should be expressed in XML syntax.</sitem>
+<sitem>XSL stylesheets should be human-readable and reasonably clear.</sitem>
+<sitem>Terseness in XSL markup is of minimal importance.</sitem>
+</slist>
+</inform-div1>
+<inform-div1>
+<head>Acknowledgements</head>
+<p>The following have contributed to authoring this draft:</p>
+<slist>
+<sitem>Sharon Adler, Inso Corporation</sitem>
+<sitem>Anders Berglund, Inso Corporation</sitem>
+<sitem>Paul Grosso, ArborText</sitem>
+<sitem>Eduardo Gutentag, Sun Microsystems</sitem>
+<sitem>Chris Lilley, W3C</sitem>
+<sitem>Chris Maden, O'Reilly &amp; Associates</sitem>
+<sitem>Jonathan Marsh, Microsoft Corporation</sitem>
+<sitem>Henry S. Thompson, University of Edinburgh</sitem>
+<sitem>Paul Trevithick, Bitstream</sitem>
+<sitem>Norman Walsh, ArborText</sitem>
+<sitem>Steve Zilles, Adobe</sitem>
+</slist>
+</inform-div1>
+<inform-div1>
+<head>Changes from Previous Public Working Draft</head>
+
+<p><code>xsl:process</code> and <code>xsl:process-children</code> have
+been combined into <code>xsl:apply-templates.</code></p>
+
+<p>The <code>expr</code> attribute of <code>xsl:value-of</code> has
+been renamed to <code>select</code>.</p>
+
+<p>Support for comments has been added.</p>
+
+<p>Support for processing instructions has been added.</p>
+
+<p>Support for text nodes has been added.</p>
+
+<p>Support for result tree numbering has been added.</p>
+
+<p>Support for sorting has been added.</p>
+
+<p>The <code>xsl:copy</code> element has been added.</p>
+
+<p>The <code>xsl:element</code> element has been added.</p>
+
+<p>The <code>xsl:attribute</code> element has been added.</p>
+
+<p>Attribute patterns have been changed: the syntax is
+<code>@foo</code> rather than <code>attribute(foo)</code>; they can be
+used as match patterns and select patterns; <code>@*</code> can be
+used to match all attributes.</p>
+
+<p>The argument to id() must now be quoted. Select patterns can also
+be used as an argument.</p>
+
+<p>The syntax for patterns has been reworked; it is now more general
+than before.</p>
+
+<p>The syntax for quoting namespaces has been changed.</p>
+
+<p>Specificity has been removed.</p>
+
+<p>Priorities can be real numbers.</p>
+
+<p>Support for processing modes has been added.</p>
+
+<p><code>xsl:apply-imports</code> has been added.</p>
+
+<p><code>define-</code> has been removed from the name of top-level
+elements. <code>xsl:attribute-set</code> now contains
+<code>xsl:attribute</code> elements.</p>
+
+<p>The default namespace (as declared with the <code>xmlns</code>
+attribute) is not used for element type names in patterns.</p>
+
+</inform-div1>
+</back>
+</spec>
diff --git a/info/examples/lwc/ch7/xslexa1.xsl b/info/examples/lwc/ch7/xslexa1.xsl
new file mode 100644
index 0000000000..988bb8f3d0
--- /dev/null
+++ b/info/examples/lwc/ch7/xslexa1.xsl
@@ -0,0 +1,30 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
+ xmlns:fo="http://www.w3.org/XSL/Format/1.0"
+ result-ns="fo">
+ <xsl:template match="/">
+ <fo:basic-page-sequence font-family="Helvetica" font-size="10pt" >
+ <xsl:apply-templates/>
+ </fo:basic-page-sequence>
+ </xsl:template>
+ <xsl:template match="par">
+ <fo:block indent-start="10pt" space-before="12pt">
+ <xsl:apply-templates/>
+ </fo:block>
+ </xsl:template>
+ <xsl:template match="emph">
+ <fo:inline-sequence font-style="italic">
+ <xsl:apply-templates/>
+ </fo:inline-sequence>
+ </xsl:template>
+<!--
+<xsl:template match='/'>
+ <fo:basic-page-sequence font-family="serif">
+ <fo:simple-page-master page-master-name='scrolling'/>
+ <fo:queue queue-name='body'>
+ <xsl:apply-templates/>
+ </fo:queue>
+ </fo:basic-page-sequence>
+</xsl:template>
+-->
+</xsl:stylesheet>