1. | HTML cross references to chunked output. |
Don't give up. There is a definite logic to the XSL stylesheet output that lets you cross reference to the HTML. It works best when each element in the target document has an id attribute. If you are seeing ch01.html, etc., then the document you are cross referencing to was chunked, meaning it was split into many HTML files. The breakpoints for chunking are at the elements named <set>, And a few others like <index>. There is an XSL parameter 'chunk.sections' which if set to true will further break up sect1 into more files. If the element that starts a new chunk has an id attribute, then that is used as the filename, plus ".html". If you are seeing "ch01.html", then that chapter element did not have an id value to make into a filename, so the XSL stylesheet had to generate a name. It does so by counting chapters in the document. The naming scheme makes sure each output filename is unique. If your document is a set of books that each have a chapter 1, then the chunked filenames use bk01ch01.html (book 1, chapter 1) and bk02ch01.html (book2, chapter 1), etc. So the filenames depend on how deeply the original XML document was structured, and whether it used id attributes in its chunking elements. Every element that doesn't start a new chunk can still be referenced if it has an id attribute, because the stylesheet inserts <a name="id"> in the HTML output at that point. So if you know the ids of the chunk and of your final destination, you can form an href like HREF="myfile.html#finalstop". If the target element does not have an id, then there won't be an <a name="*" > tag in the HTML output, so you can't reference it directly. Working with filenames that are generated is risky, because if the document is rearranged the numbering will change. That's why I said it works best if all the elements you want have ids. | |
2. | How do I add something to the HTML navigational header or footer? |
Applicable to 1.48 and after stylesheets. When you process your document in chunk mode, each HTML output file includes a header and footer that provide navigational links. The stylesheets provide a couple of empty templates that allow you to add to the header or footer. To add to something above the navigational header, like a company logo, you define the content in a template named <xsl:template name="user.header.content">
<IMG>
<xsl:attribute name="src">graphics/companylogo.png</xsl:attribute>
</IMG>
</xsl:template>The content of this template always appears first on each HTML page. Likewise, to add something below the navigational footer, such as copyright information, you define content in a template named If you want to rearrange the headers and footers beyond these additions, you'll need to redefine the templates that the stylesheet uses to generate the standard header and footer content. Those templates are named | |
3. | Images for next and previous pages in chunked output |
You can replace the text for Next and Previous with graphics in the navigational headers and footers of HTML output that is chunked into separate files. This feature is controlled by a set of stylesheet parameters, starting with version 1.48 of the DocBook stylesheets. Add these parameter settings to your HTML stylesheet customization layer. <xsl:param name="navig.graphics" select="1"/> <xsl:param name="navig.graphics.extension" select="'.gif'"/> <xsl:param name="navig.graphics.path">images/</xsl:param> <xsl:param name="navig.showtitles" select="1"/>
| |
4. | Address Layout in HTML |
You could just write the address that way: <address>Free Software Foundation,Inc., 59 Temple Place The problem you're running into is that <address> has "verbatim" semantics. So that you can write <address>Some Street and have it display that way (rather than getting all run together). But if you don't want a | This leads to the make-verbatim template which is almost a complete mystery. Yeah, it's a pretty hairy template. Basically it recurses to walk over the content of the address so that it can replace the characters it needs to. 
 is a linefeed. | Below is the start of the customization of address. What does your source markup look like? Let's assume it's: <address><street>Free Software Foundation,Inc.<street> Try: <xsl:template match="legalnotice/address"> Untested. | |
5. | Changing Fonts - HTML output |
This is most easily done by associating a CSS stylesheet with the HTML output. You can do that with the 'html.stylesheet' parameter. If you look in the generated HTML output, you'll see each element is in a <div> with its name, which makes writing css stylesheets that style specific elements easy. | |
6. | Creating an index |
"IndexTerms mark either a single point in the document or a range. A single point is marked with an IndexTerm placed in the text at the point of reference. There are two ways to identify a range of text: * Place an IndexTerm at the beginning of the range with Class set to StartOfRange and give this term an ID. Place another IndexTerm at the end of the range with StartRef pointing to the ID of the starting IndexTerm. This second IndexTerm must be empty. The advantage of this method is that the range can span unbalanced element boundries. * Place the IndexTerm anywhere you like and point to the element that contains the range of text you wish to index with the Zone attribute on the IndexTerm. Note that Zone is defined as IDREFS so a single IndexTerm can point to multiple ranges. The advantage of this method is that IndexTerms can be collected together or even stored totally outside the flow of the document (in the meta for example)." I.e., you can build an external list of elements, provided they have IDs, and then associate IndexTerm elements with those elements using IDREFs. It is of course not feasible to put an ID on every word in the body text; you'll have to find an enclosing element and ensure it has the ID attribute. You can populate elements with unique IDs at document creation time or as a separate processing step. Theoretically, even without IDs it might be feasible to point to anywhere in the document with a XPath expression (or similar HyTime construct); in practice, it won't be stable without dependable IDs. If you manage to get something XPath-aware working, you can point to a range of #PCDATA inside an element, but it might not be needed. For online presentation, page numbers does not make much sense anyway, and for typeset paginated presentation, you can usually get away with refering to an eclosing element. | |
7. | Labels in QandADivs |
Reading the html/qandaset.xsl stylesheet module, the bold is for the label. If you had not set <qandaset defaultlabel="none">, then your answer would start with "<b>A:</b>", or whatever the translation of that label would be in another language. The "A:" comes from common/en.xml as the generated text for the label of an <answer> element. | |
8. | Automatic generation of map and alias files |
I have just added some new functionality to HTML Help stylesheet related to automatic generation of map and alias files. These files are used to glue application and context sensitive help made in HTML Help. From now, you can use special PI in documents: <chapter> <title>Some title</title> <?dbhh topicname="some_title" topicid="42"?> ... This will automatically create corresponding entries in map and alias files: context.h: If you want different names for context.h and alias.h, you can use parameters htmlhelp.map.file and htmlhelp.alias.file to change it. If you want create context.h and alias.h manually, stylesheet can automatically include reference to them in project file if you set parameter htmlhelp.force.map.and.alias to 1. I will appreciate your feedback about this extension as I personally don't use it in any real application. The idea comes from my correspondence with Denis Bradford. | |
9. | Using Microsoft XML parser with docbook |
I've had good luck with it. There's a situation where msxml gets confused resolving entities. I can't remember what it is, but it seems like it is not the same 'relative to the place it was used rather than declared' problem that Saxon used to have. Can I display the 'styled' docbook from the XML source using Microsoft kit? Yes! You need only to add the following line to your xml file directly
after the xml-prolog ( <?xml-stylesheet type="text/xsl" href="uri/or/location/of/xsl/stylesheet" ?> I've tried this with a quite large document and some older version of the DocBook-XSL-Stylesheet. It worked pretty fine. But take care of the different versions of the MSXML-Parser (IE build-in parser). If your are using IE 5.x you might have MSXML 2.5 installed on your system. I've tried it with MSXML 3.0 wich works much better. (DaveP. and version 4 even better) You can download the new releases of the MSXML-Parser from http://msdn.microsoft.com. Note that the parser installs itself in a so called side-by-side mode. This mode doesn't replace the parser within IE. You have to download and install another small programm wich replaces the parser (I think ist called xmlinst). There is a good description about how to install the parser on the MSDN. Be sure that you take the single-output-file-stylesheet. It doesn't supports chunking the way Saxon or Xalan do. So use the docbook.xsl-Stylesheet in the HTML directory of the XSL-Stylesheet to ge a nice HTML-Output ;-) Microsoft unofficial help page for further MS help. | |
10. | Ordered lists have extra spaces between lines |
This is, IMHO, a browser issue. The content model of LI clearly allows P and there's no reason why the browsers should do what they do. That said, lots of people would like it to work differently. It would be fairly easy to suppress the P on listitems containing a single paragraph, so I suppose that's what I should do. I hesitate because it would create some inconsistencies if some listitems in the list contained more than one paragraph. Actually, this is already supported! If a listitem contains only a single 'simpara', the P wrapper is suppressed. | |
11. | Controlling the table of contents in XSL stylesheets |
The TOC processing machinery for a chapter starts in the "component.toc" template, which is in the autotoc.xsl file. That template outputs the localizes "Table of Contents" title, and then does apply-templates in mode="toc". The templates in that file that use that mode call the "subtoc" template recursively to build the TOC from the element and its children. It is "subtoc" that actually outputs the <dl> elements, so that is where you would want to concentrate your efforts on customizing the format of a TOC, probably by providing a replacement subtoc template. | |
12. | table of contents labels |
I think that setting id attribute on component container (chapter, section, ...) will help. Content of ID should be used then instead of autogenerated value. > b) Will these "labels" stay constant accross each iteration Usually yes, but XSLT specifications says that they can be different in each transformation. | |
13. | Table Column widths |
That's why CALS allows relative units. If you set pagewide=1, you're asking for the table to be coerced to the page width. If you don't, you're giving the renderer a free hand to build a table that may be narrower than the available page width. (Note that in a multi-column environment, there's no equivalent colwide=1; if you set pagewide=1, you're implicitly asking for the table to span all the columns.) For example Here's a table that will be formatted such that the first column is always three units wide and the second column is always two units wide, where "units" is a relative measure left up to the formatter. <informaltable> <tgroup cols="2"> <colspec colwidth="3*"/> <colspec colwidth="2*"/> ... | |
14. | Output div as top level element, html mode |
No parameter, but an easy customization. Currently the HTML head stuff is output by this template in html/docbook.xsl:
If you only want to modify this for articles, you could add a template in mode "process.root" to your html customization layer: <xsl:template match="article" mode="process.root">
<xsl:apply-templates select="."/>
</xsl:template>
Then it will not output the <head><body> stuff, but it will process everything in the document as html. | |
15. | Shading programlisting |
Shading has nothing to do with the content of your docbook document. It's a property of the presentation and has to be applied when you generate the HTML -- that's why you won't find it in TDG. sourceforge.net is the HTML parameter reference, and under "miscellaneous", you'll find the entries for shade.verbatim and shade.verbatim.style that you can use when you transform docbook to html. i just tried it -- works fine. If you check the description of, say, <programlisting>, you'll notice that it describes itself as "verbatim", so it should have shading applied to it via that parameter. | |
16. | Numbering sections, |
Setting the stylesheet parameter 'section.autolabel' to 1 turns on section numbering. If you also want the section numbers to include the chapter number as the first part of the number, then also set the 'section.label.includes.component.label' parameter to 1. | |
17. | Pop up sidebars in HTML? |
That's not a a built-in feature, so you would have to write a customization to do that. You need to write a replacement XSL template for <xsl:template match="sidebar"> (the original is in html/block.xsl in the DocBook XSL distribution, but it doesn't do much). The things it would need to do include: 1. Figure out a unique filename for each popup. 2. Call the 'write.chunk' template with the correct set of parameters, including the content. 3. Generate an anchor of some sort so the user knows there is a sidebar and can click to reach it. The anchor might look like this:
| |
18. | meta tags |
For these two meta names, there is some direct support in Docbook XSL. For "description", if you put your description in the document's <abstract> element, and set the stylesheet parameter 'generate.meta.abstract' to 1, then the text of the abstract will appear as the 'content' value of the meta. For keywords, if you put a <keywordset> element with keywords in your document's *info element (bookinfo, chapterinfo, etc), then it will be output in a meta name="keywords" element in the HTML HEAD. If you want other meta elements, or you want to customize how the description meta is handled (passed as a parameter, for example), then you can customize the built-in placeholder template named 'user.head.content'. It is automatically called during the output of the HTML HEAD. | |
19. | Using CSS |
Yes, see: sagehill | |
20. | Using an external CSS stylesheet |
I would like to embed the contents of an external css stylesheet at user.head.content. That is, instead of a link to the stylesheet (a la html.stylesheet), I would like a document-level <style> block in the head of the document. I want to pull the css rules in from an external, shared file, rather than hardwiring them in the stylesheet. Try this (where html.css is your css): <?xml version="1.0" encoding="US-ASCII"?> <!DOCTYPE stylesheet [ <!ENTITY css SYSTEM "html.css"> ]> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:doc="http://nwalsh.com/xsl/documentation/1.0" exclude-result-prefixes="doc" version="1.0"> <xsl:template name="user.head.content"> <style type="text/css"> &css; </style> </xsl:template> </xsl:stylesheet> | |
21. | Output the doctype |
If you are referring to HTML output, using xsl:output is not the only way. The chunking stylesheet accepts the 'chunker.output.doctype-public' and chunker.output.doctype-system' parameters to specify a DOCTYPE for the output. If you need it for single file output, you can use the onechunk stylesheet, which also accepts those parameters. See this reference for an example: on my site | |
22. | Empty Table Cells |
Those aren't Control-A's you are seeing, they are the UTF-8 encoding of the non-breaking space character (00A0 in Unicode). The two-character sequence in UTF-8 encoding is C2 and A0. Most browsers support UTF-8, and the XHTML output should indicate the encoding with: <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> That should be enough for the browser to recognize the character as a space character, not as an unknown character. What browser are you using? The reason the nonbreaking spaces are output to empty cells is because some browsers don't properly handle cell border display for truly empty cells. | |
23. | Creating Index terms from Glossary entries |
To answer my own question: I had the same problem a year ago, and I believe it was David Cramer who sent me a stylesheet that appends an <indexterm> stanza after each relevant <glossterm> entry. At the time I was still using DSSSL so I didn't know what to do with it. Now I tried it, and it gives a very good first impression. I attach David's stylesheet. It works as a first run of xsltproc, producing an intermediate DocBook text that can be further processed by xsltprocw ith another stylesheet, and fop . I did not get it to work when included into a stylesheet that aims to produce the .fo file in one run.
<?xml version="1.0"?>
<!-- I made the default namespace null to avoid having
Saxon put a saxon name space on the indexterm elements we're writing out -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns=""
version="1.0">
<xsl:output
method="xml"
indent="yes"/>
<!-- By default, copy everything -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- For glossterms outside of the glossary, copy the element,
but add an index marker immediately after it. UNLESS it's
<glossterm role="no indexterm">; this gives the writer the
ability to put in a glossterm and avoid having it create an
indexterm marker. -->
<xsl:template match="glossterm[not(ancestor::glossary) and
not(@role = 'no indexterm')]">
<xsl:copy-of
select="."/><indexterm><primary><xsl:value-of
select="."/><
/primary></indexterm>
</xsl:template>
<!-- This handles glossterms in the glossary as a special case -->
<xsl:template match="glossentry">
<glossentry>
<xsl:copy-of select="@*"/>
<xsl:copy-of select="glossterm"/>
<xsl:copy-of select="acronym"/>
<xsl:copy-of select="abbrev"/>
<indexterm><primary><xsl:value-of
select="glossterm"/></primary></indexterm>
<xsl:copy-of select="revhistory"/>
<xsl:copy-of select="glosssee"/>
<xsl:copy-of select="glossdef"/>
</glossentry>
</xsl:template>
</xsl:stylesheet>
| |
24. | Xref within index |
The template you want to customize is this one in xhtml/index.xsl: <xsl:template match="indexentry"> <xsl:apply-templates select="primaryie"/> </xsl:template> Change it to this in your customization layer: <xsl:template match="indexentry"> <xsl:call-template name="anchor"/> <xsl:apply-templates select="primaryie"/> </xsl:template> I guess no one ever asked to cross reference between index entries before. It's a bit unusual to write the index by hand using <indexentry> elements, when the stylesheet can generate the index from <indexterm> elements embedded in your document. Are you doing it this way so you can hot link between index entries? I don't see how your entries link into the body of the text, though. Hot linking see and seealso entries is not currently a stylesheet feature, but it seems like it would be a good one. | |
25. | Missing cross-references |
Put the id on the <figure> rather than the <caption>. You can xref to most elements that have <title>s, but you have to xref to the element itself. See Bob's book for all the details and options: http://www.sagehill.net/docbookxsl/CrossRefs.html | |
26. | Index and indexterm in website |
Well, there's good news and there's bad news. The good news is that index and indexterm are permitted inside a webpage element whose DOCTYPE is website-full.dtd, and they do validate. I just tested it. I'm not sure what's going wrong when you try it. The bad news is that they don't do what you want them to do, which is create an index for your website. You have to keep in mind that each webpage document is a separate XML document, and it is processed as a separate document. That means the scope of an index can be no larger than one webpage document. In order for the index to cover all your webpages, they would have to be included as children of a larger container document that is processed all at once. But that isn't how Website works. As it currently ships, Website can't collect index entries from the set of webpage documents and generate a sorted index. | |
27. | Right to Left in markup |
there are several ways to turn your flow of text into the "right direction". (1) With HTML, the most effective one seems to use the BDO element (an inliner) and the DIR attribute to specifiy the text direction. For example, use:
<p>Some left to right text <bdo
dir="rtl">Some right to left text</bdo>
Some more ltr...<p>
The DIR attribute is also available for several other elements in HTML 4.01, most notably P and BODY. This will also right-align your text in the browser. Just have a look at the HTML spec for more information. (e.g.http://www.w3.org/TR/html401/struct/dirlang.html#h-8.2) I don't know how the different browsers support this, but I'm confident that at least the most prominent will do. (2) It is true that the current FOP release (0.20.5) does not support BIDI. But there are some hacks to serve that purpose. Maybe you will find some more information on the FOP mailing list at http://xml.apache.org/fop/maillist.html. The forthcomimg release of FOP (1.0) is said to support BIDI. As far as I know, the remaining suspects (namely XEP by RenderX and XSL Formatter by Antenna House) support BIDI. But these are commercial tools. | |
28. | Right to left and left to right directional tags |
OK, I understand now what you mean by saying it is LTR. Not the phrases in Arabic in the table, but the layout of the table itself. Then what you want is not Unicode BIDI marks, but <body style="direction: rtl"> that is, the default mode is right to left. I've just checked it with your file, it worked. Forget about Unicode BIDI marks; use CSS instead. A description of the property is at zvon Additionally, zvon is a very good resource for references and tutorials on many things including CSS. Again, you don't need to set the order of characters in words or of words in phrases, just the layout of the page. It does not know otherwise that you want rtl by default (and it is written by people who think that default is ltr, sigh). | |
29. | Stylesheet support for revisionflag element |
Yes, use changebars.xsl stylesheet instead of docbook.xsl. | |
30. | Indexterms in FAQ Questions result in duplicate text? |
You have run into one of the compromises that the stylesheet has to make for HTML. In the case of the QandA table of contents, it processes the question element by using <xsl:value-of> on the first child element of <question>. That gets just its string value, and so the indexterm text is included. It gets the string value because it puts it inside an HTML <a> element. Since a question element can contain arbitrary content, including other cross references, that would lead to bad HTML because you can't nest links within links in HTML. You can work around the problem by putting the <indexterm> after the closing </para> tag within the <question>. That way it will not be included in the first child of question, and it should still work. | |
31. | Variant toc depths, set and book |
If you want to retain the depth of the book tables of contents while reducing the depth of the set table of contents, you will have to do a little customization. The template named 'make.toc' in autotoc.xsl is called at the beginning of a table of contents, and then it applies templates in mode="toc" for each nested level. As it applies templates in that mode, it supplies the 'toc-context' parameter whose value is the top element containing the TOC. You want to change how a book is processed when the toc-context is set. So copy the match="book" mode="toc" template from autotoc.xsl to your customization layer and add an xsl:choose to modify the behavior:
<xsl:template match="book" mode="toc">
<xsl:param name="toc-context" select="."/>
<xsl:choose>
<xsl:when test="local-name($toc-context) = 'set'">
<xsl:call-template name="subtoc">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="nodes" select="foo"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="subtoc">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="nodes" select="part|reference
|preface|chapter|appendix
|article
|bibliography|glossary|index
|refentry
|bridgehead[$bridgehead.in.toc !=0]"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
In the xsl:when statement, if the toc-context is 'set', then call subtoc with no nodes selected (I entered a fake element name because it won't accept an empty select statement). The subtoc template will format the book title, and then won't have any subnodes to process. | |
32. | Processing large Cals tables |
THE PROBLEM big oasis-open/cals tables, i.e. tables with more than ca. 500 rows cause Saxon 6.5.3 and Xalan 2.5.2 to throw an StackOverflowError, no matter how much stack size is allocated. i am not sure whether the problem is with the processors, or Java. note that MSXML3 (not sure about the version) does handle the conversion. note as well that oXygen's xslt debugger is also able to convert the table using Saxon 6.5.3, after warning you that a possible infinite loop has been detected (you have to say yes, you want to continue anyway). THE CAUSE apparently, the cause for this is in the recursiveness of the stylesheets used. I used the Docbook xsl stylesheets 1.65.1 which include oasis-open/cals table transformation stylesheets. THE SOLUTION i've been given a stylesheet which conforms to xslt2, and can be run with Saxon 7 which does the transformation. it is "tail-recursive" which means less stack is used. i have successfully used it for a table of 1753 rows. it is still long, i.e. ca. 12 minutes on a P4 2.4GHz with 512MB. obviously, it would have been nice to stay with xslt1, and to do it quicker, but hey, it works! CREDITS John Mullee wrote and has me provided with the stylesheet, thanks a lot! All the other people on docbook-apps and saxon-help who took the time to respond, thank you! Norman Walsh and team for their xslt docbook stylesheets (i'm still using the table stylesheets for all "normal" tables). SEE ALSO [1] on the saxon-help mailing list, search for this title "OASIS-Open/CALS *big* table conversion problems", for posts related to this issue. [2] with John's permission: his stylesheet, the table in question, the output etc. are available on his site (via tinyurl): http://tinyurl.com/25mkc Ednote: Inserted here, unsure of the longevity of those links
<!-- (c) john mullee 2004 - copyright placed in the public domain -->
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet version="2.0"
xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"
xmlns:xs= "http://www.w3.org/2001/XMLSchema"
xmlns:local ="http://127.0.0.1/cals_to_html.xslt"
exclude-result-prefixes="#all"
>
<xsl:output
method = "html"
doctype-public = "-//W3C//DTD HTML 4.01 Transitional//EN"
encoding = "UTF-8"
escape-uri-attributes = "yes"
include-content-type = "yes"
indent = "yes"
/>
<!--
CALS Table Model
http://www.oasis-open.org/specs/a502.htm
http://www.oasis-open.org/cover/tr9502.html
OASIS XML Exchange Table Model
http://www.oasis-open.org/specs/a503.htm
http://www.oasis-open.org/specs/tm9901.htm
Some test cases:
http://sources.redhat.com/ml/xsl-list/2001-07/msg00835.html
* Subject: Re: [xsl] Table formatting challenge
* From: Norman Walsh <ndw at nwalsh dot com>
".. Here are a few more examples (that thwart the code you presented)"
-->
<xsl:template match="node()|@*" mode="html-only"
xpath-default-namespace="http://www.w3.org/1999/xhtml">
<xsl:choose>
<xsl:when test="compare(local-name(), name())=0">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="@*|node()" mode="html-only"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="node()" mode="html-only"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<html>
<head>
<style type="text/css">
td.generated { background-color: green; }
</style>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<!-- ===================== -->
<!-- dummy for Jakob's xml -->
<xsl:template match="para">
<xsl:choose>
<xsl:when test="count(node()) > 0">
<p>
<xsl:apply-templates/>
</p>
</xsl:when>
<xsl:otherwise> </xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="anote"><a
href="#{@refid}">(LINK <xsl:apply-templates/>)</a>
</xsl:template>
<xsl:template match="note"><a
name="{@id}"/><xsl:apply-templates/></xsl:template>
<!-- ===================== -->
<!-- CHANGE xsl:template match="informaltable"-->
<xsl:template match="table">
<xsl:apply-templates select="tgroup" mode="XML_ExTabModel"/>
</xsl:template>
<!-- XML_ExTabModel mode -->
<xsl:template match="tgroup" mode="XML_ExTabModel">
<table border="1" summary="">
<caption>
<!-- not part of XML_ExTabModel -->
</caption>
<colgroup span="{@cols}">
<xsl:for-each select="colspec">
<col span="1" width="{@colwidth}">
<xsl:call-template name="general_cell_alignment">
<xsl:with-param name="element" select="."/>
</xsl:call-template>
</col>
</xsl:for-each>
</colgroup>
<xsl:apply-templates select="thead" mode="XML_ExTabModel"/>
<tfoot>
<!-- not part of XML_ExTabModel -->
</tfoot>
<xsl:apply-templates select="tbody" mode="XML_ExTabModel"/>
</table>
</xsl:template>
<xsl:template match="thead" mode="XML_ExTabModel">
<thead>
<xsl:call-template name="general_cell_alignment">
<xsl:with-param name="element" select="."/>
</xsl:call-template>
<xsl:call-template name="recursive_row_processor"/>
</thead>
</xsl:template>
<xsl:template match="tbody" mode="XML_ExTabModel">
<tbody>
<xsl:call-template name="general_cell_alignment">
<xsl:with-param name="element" select="."/>
</xsl:call-template>
<xsl:call-template name="recursive_row_processor"/>
</tbody>
</xsl:template>
<!-- ===== recursive row processing ======= -->
<xsl:template name="recursive_row_processor">
<xsl:param name="curr_row" as="xs:integer" select="1"/>
<xsl:param name="set_of_rows" as="element()*" />
<xsl:message>recursive_row_processor <xsl:value-of
select="$curr_row"/></xsl:message>
<xsl:variable name="num_rows" select="count(./row)"/>
<!-- add a new row to set -->
<xsl:variable name="new_set_of_rows" as="element()*">
<xsl:copy-of select="$set_of_rows"/>
<xsl:apply-templates select="./row[$curr_row]"
mode="XML_ExTabModel">
<!-- generated rows are forwarded to cell generator
for rowspan lookup -->
<xsl:with-param name="set_of_rows" select="$set_of_rows"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:choose>
<xsl:when test="$curr_row = $num_rows">
<!-- terminate recursion, output rows -->
<!-- copy without local-namespace stuff -->
<xsl:apply-templates select="$new_set_of_rows"
mode="html-only"/>
</xsl:when>
<xsl:otherwise>
<!-- tail-recurse for more rows -->
<xsl:call-template name="recursive_row_processor">
<xsl:with-param name="curr_row"
select="xs:integer($curr_row + 1)"/>
<xsl:with-param name="set_of_rows"
select="$new_set_of_rows"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="XML_ExTabModel">
<xsl:param name="set_of_rows" as="element()*" />
<tr>
<xsl:if test="ancestor::thead">
<xsl:attribute name="bgcolor" select="'#999999'"/>
</xsl:if>
<xsl:call-template name="general_cell_alignment">
<xsl:with-param name="element" select="."/>
</xsl:call-template>
<xsl:call-template name="recursive_cell_processor">
<xsl:with-param name="set_of_rows" select="$set_of_rows" />
</xsl:call-template>
</tr>
</xsl:template>
<!-- ===== recursive cell processing ======= -->
<xsl:template name="recursive_cell_processor">
<xsl:param name="curr_entry" as="xs:integer" select="1"/>
<xsl:param name="curr_column" as="xs:integer" select="1"/>
<xsl:param name="set_of_cells" as="element()*"/>
<xsl:param name="last_cell" as="document-node()?"/>
<xsl:param name="set_of_rows" as="element()*"/>
<xsl:variable name="num_columns" select="../../@cols"/>
<xsl:variable name="num_entries" select="count(entry)"/>
<xsl:variable name="current_row" select="count($set_of_rows) + 1"/>
<xsl:variable name="cells_spanning_rows">
<!-- build a list of row-spanning cells which will affect
this row -->
<xsl:for-each
select="$set_of_rows[ td/@rowspan >= ($current_row - position()) ]">
<!-- context = TR containing a cell which rowspans
across current row -->
<xsl:variable name="row_id" select="generate-id(.)"/>
<!-- BUG this relies on id-strings Collating in
document-order
: saxon 7 works -->
<xsl:variable name="rowndx"
select="count($set_of_rows[$row_id > generate-id(.)])"
as="xs:integer"/>
<xsl:for-each select="td[@rowspan]">
<!-- context = TD's containing rowspan -->
<xsl:if test="(@rowspan + $rowndx) >= $current_row">
<!-- TD's which spans across current row -->
<xsl:for-each select="@local:beg to @local:end">
<span col="{.}"/>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<!-- adjust for the special case of the first column being
overlapped -->
<xsl:variable name="adjusted_curr_column_list" as="xs:integer+">
<xsl:choose>
<xsl:when test="count($cells_spanning_rows/span[@col =
$curr_column]) > 0">
<!-- build a list of col numbers which follow
contiguous series' of col numbers -->
<xsl:for-each
select="$cells_spanning_rows/span">
<xsl:sort
select="number(@col)"/>
<xsl:choose>
<xsl:when test="following-sibling::node()[1]/@col">
<xsl:if test="not(xs:integer(@col) =
xs:integer(following-sibling::node()[1]/@col - 1))">
<xsl:value-of select="@col + 1"/>
</xsl:if>
<!-- otherwise, context is within
contiguous series -->
</xsl:when>
<xsl:otherwise><xsl:value-of
select="@col + 1"/></xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise><xsl:value-of
select="$curr_column"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="adjusted_curr_column"
as="xs:integer" select="$adjusted_curr_column_list[1]"/>
<!-- build another table cell -->
<xsl:variable name="built_cell">
<xsl:call-template name="build_table_cell">
<xsl:with-param name="entry" select="entry[$curr_entry]"/>
<xsl:with-param name="curr_column"
select="$adjusted_curr_column"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="next_cell_start"
select="$built_cell/td/@local:beg"/>
<xsl:variable name="next_cell_end"
select="$built_cell/td/@local:end"/>
<xsl:variable name="last_cell_end"
select="$last_cell/td/@local:end"/>
<xsl:variable name="num_prev_cells"
select="count($set_of_cells[name()='td'])"/>
<!-- add new cell to existing set of cells -->
<xsl:variable name="new_set_of_cells" as="element()*">
<!-- insert any cells needed at beginning of row -->
<xsl:if test="($curr_entry = 1) and ($next_cell_end > 1)">
<xsl:call-template name="add_empty_cells">
<xsl:with-param name="count"
select="xs:integer($built_cell/td/@local:beg - 1)"/>
<xsl:with-param name="start" select="xs:integer(1)"/>
<xsl:with-param name="cells_spanning_rows"
select="$cells_spanning_rows"/>
</xsl:call-template>
</xsl:if>
<!-- emit the previously-generated cells -->
<xsl:copy-of select="$set_of_cells"/>
<!-- fill in any gap between prev cell and this -->
<xsl:if test="($num_prev_cells > 0) and
($next_cell_start > ($last_cell_end + 1))">
<xsl:call-template name="add_empty_cells">
<xsl:with-param name="count"
select="xs:integer($next_cell_start - ($last_cell_end + 1) )"/>
<xsl:with-param name="cells_spanning_rows"
select="$cells_spanning_rows"/>
<xsl:with-param name="start"
select="xs:integer($last_cell_end + 1)"/>
</xsl:call-template>
</xsl:if>
<!-- emit the cell we just generated -->
<xsl:copy-of select="$built_cell"/>
<!-- last entry: insert any cells needed at end of row -->
<xsl:if test="($curr_entry = $num_entries) and
($next_cell_end < $num_columns)">
<xsl:call-template name="add_empty_cells">
<xsl:with-param name="count"
select="xs:integer($num_columns - $next_cell_end)"/>
<xsl:with-param name="cells_spanning_rows"
select="$cells_spanning_rows"/>
<xsl:with-param name="start"
select="xs:integer($built_cell/td/@local:end + 1)"/>
</xsl:call-template>
</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="not($curr_entry = $num_entries)">
<!-- tail-recurse for more cells -->
<xsl:call-template name="recursive_cell_processor">
<xsl:with-param name="curr_entry"
select="$curr_entry + 1"/>
<xsl:with-param name="curr_column"
select="xs:integer($next_cell_end + 1)"/>
<xsl:with-param name="set_of_cells"
select="$new_set_of_cells"/>
<xsl:with-param name="last_cell"
select="$built_cell"/>
<xsl:with-param name="set_of_rows" select="$set_of_rows"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- terminate recusion, output cells -->
<xsl:copy-of select="$new_set_of_cells"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- ===== column numbering ======= -->
<xsl:function name="local:fn_get_col_number" as="xs:integer">
<xsl:param name="context_tgroup"/>
<xsl:param name="colname"/>
<xsl:param name="default" as="xs:integer"/>
<xsl:choose>
<xsl:when test="$colname">
<xsl:choose>
<xsl:when
test="$context_tgroup/colspec[@colname=$colname]/@colnum">
<xsl:value-of
select="xs:integer($context_tgroup/colspec[@colname=$colname]/@colnum)"/>
</xsl:when>
<xsl:otherwise>
<!-- BUG there might be no preceding colspec -->
<xsl:value-of
select="count($context_tgroup/colspec[
@colname=$colname]/preceding-sibling::*[name()='colspec'])+1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise><xsl:value-of
select="$default"/></xsl:otherwise>
</xsl:choose>
</xsl:function>
<!-- ===== adding empty cells ======= -->
<xsl:template name="add_empty_cells">
<xsl:param name="count" as="xs:integer" select="0"/>
<xsl:param name="start" as="xs:integer" select="0"/>
<xsl:param name="cells_spanning_rows"/>
<xsl:for-each select="$start to ($start + $count - 1)">
<xsl:variable name="col_index" select="." as="xs:integer"/>
<xsl:if test="count($cells_spanning_rows/span[@col =
$col_index]) = 0">
<td class="generated" local:beg="{$start + position()}"
local:end="{$start + position()}"> </td>
</xsl:if>
</xsl:for-each>
</xsl:template>
<!-- ===== table cell ======= -->
<xsl:template name="build_table_cell">
<xsl:param name="entry"/>
<xsl:param name="curr_column"/>
<xsl:variable name="start_col_pos"
select="local:fn_get_col_number($entry/ancestor::tgroup,
$entry/@namest, $curr_column)"/>
<xsl:variable name="end_col_pos"
select="local:fn_get_col_number($entry/ancestor::tgroup,
$entry/@nameend, $start_col_pos)"/>
<xsl:variable name="computed_col_span"
select="xs:integer(($end_col_pos - $start_col_pos) + 1)"/>
<!-- output results element and TD -->
<td local:beg="{$start_col_pos}" local:end="{$end_col_pos}">
<xsl:call-template name="general_cell_alignment">
<xsl:with-param name="element" select="$entry"/>
</xsl:call-template>
<!-- colspan -->
<xsl:if test="$computed_col_span > 1">
<xsl:attribute name="colspan">
<xsl:value-of select="$computed_col_span"/>
</xsl:attribute>
</xsl:if>
<!-- rowspan -->
<xsl:if test="$entry/@morerows">
<xsl:if test="number($entry/@morerows)>0">
<xsl:attribute name="rowspan">
<xsl:value-of select="number($entry/@morerows)+1"/>
</xsl:attribute>
</xsl:if>
</xsl:if>
<!-- nbsp for empty cells -->
<xsl:if test="count($entry/node()) = 0"> </xsl:if>
<!-- proceed in Non-XML_ExTabModel mode -->
<xsl:apply-templates select="$entry"/>
</td>
</xsl:template>
<!-- ===== alignment attributes ======= -->
<xsl:template name="general_cell_alignment">
<xsl:param name="element"/>
<xsl:if test="$element/@align">
<xsl:attribute name="align">
<xsl:choose>
<xsl:when test="string-length(string($element/@align))>0">
<xsl:value-of
select="replace($element/@align,'justify','left')"/>
</xsl:when>
<xsl:otherwise>center</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
<xsl:if test="$element/@valign">
<xsl:attribute name="valign">
<xsl:choose>
<xsl:when
test="string-length(string($element/@valign))>0">
<xsl:value-of select="$element/@valign"/></xsl:when>
<xsl:otherwise>top</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
<xsl:if test="$element/@char">
<xsl:attribute name="char">
<xsl:choose>
<xsl:when
test="string-length(string($element/@char))>0">
<xsl:value-of select="$element/@char"/></xsl:when>
<xsl:otherwise>%</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
<xsl:if test="$element/@charoff">
<xsl:attribute name="charoff">
<xsl:choose>
<xsl:when
test="string-length(string($element/@charoff))>0">
<xsl:value-of select="$element/@charoff"/></xsl:when>
<xsl:otherwise>3</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
<xsl:if test="$element/@width">
<xsl:attribute name="width">
<xsl:choose>
<xsl:when
test="string-length(string($element/@width))>0">
<xsl:value-of select="$element/@width"/></xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
| |
33. | Chunks for abstract and toc |
The toc is easy. Just set the parameter 'chunk.toc.and.lots' to 1 and you will get a separate chunk. The abstract is not so easy because there is no parameter to do it. It will require a customization. But you can basically copy what is done for legalnotice when the 'generate.legalnotice.link' parameter is set to 1. That code is in html/titlepage.xsl in the template that starts with: <xsl:template match="legalnotice" mode="titlepage.mode"> | |
34. | Add document title to each chunk |
You could use the 'user.header.content' template to add an H1 heading to every chunked file. To merge the document title with each section title, you could customize the template named 'section.heading' from html/sections.xsl to output the document title before the section title. For chapters and other component-level elements, you would also need to customize the template named 'component.title' in html/component.xsl in a similar manner. | |
35. | Image size |
Better will be to use width="100%" (no need for scalefit) so your images will stretch if you will change paper size. |