Next in thread →
Next in month →
Re: [docbook-apps] variablelist styles
Hi Laurie,
If you are wondering why the whitespace in
<term> is kept but other whitespace is not, it is because the content
model for term includes #PCDATA. That makes it a "mixed content" element,
which means it mixes characters with elements. That means all characters
including whitespace characters are considered part of the content and
cannot be ignored by the processor.
Handling whitespace in mixed content elements is
indeed complicated, as David says. Because term is processed by using
xsl:apply-templates, you can create a template that matches on your special
case. Something like:
<xsl:template
match="term/text()[count(preceding-sibling::node()) = 0]">
The problem is, what do you do with this text node
once you find it? Unfortunately, in XSLT 1.0 there are no regular
expressions to match on combinations of whitespace at the beginning of a string
as there are in other languages (they exist in XSLT 2.0). Your case has a
line feed and a space indent to handle, but there could be two spaces, or a
space before the linefeed that isn't visible, etc. Sometimes authors hit
the tab key too. You end up writing a recursive template that steps
through the text string one character at a time and uses an xsl:choose for all
the cases to decide to discard it or keep it. It can be done, but it
requires careful attention to detail.
The best practice is to be aware of mixed content
elements and not add such white space content in the authoring step. I
wish I could give you a list of elements with mixed content, but I can't seem to
locate one offhand.
The pretty printer function in an XML editor that
is aware of the schema should never break and indent mixed content elements
when pretty printing. I'm not aware of the extent of this support, though.
It was fixed recently in Oxygen 11, for example. If you cannot rely on
your pretty printer to not insert inappropriate spaces (is that a triple
negative?), then avoid using it.
Bob Stayton
Sagehill Enterprises
----- Original Message -----
From:
David Cramer
To: Laurie Burley ;
Sent: Wednesday, March 03, 2010 9:09
AM
Subject: RE: [docbook-apps] variablelist
styles
Ok, the problem is the whitespace between <term>
and <guilabel>. It's collapsed to a single space when the doc is parsed,
but that space is kept. A simple solution that would solve that problem (but
cause some others) is to change:
<xsl:apply-templates select="term"/>
to:
<xsl:value-of
select="normalize-space(term)"/>
That will ensure that you get the text nodes of the term
element with preceding and trailing whitespace removed BUT you also lose any
markup. For example, If you have <term><emphasis
role="italic">Foo</emphais> bar</term> and you expected
to see "Foo" in italics, you would be dissapointed. Also, if you for
some reason did <term>See <xref
linkend="blah"/></term> the xref would be dropped. So it's
dangerous.
Otherwise, I think you'd have to use apply-templates to
get the term into a variable, write some xsl that inspects the beginning text
node (if there is one), and uses substring on that node to remove the first
space if there is one. Sounds kind of hairy. Maybe Bob or someone has a better
idea or there's some exisiting convenient way to handle that situation.
If your editor lets you control the pretty printing it
does on the document, you could configure it not to but a linebreak before
inline elements and after the beginning <term> tag.
David
From: Laurie Burley
[mailto:]
Sent: Wednesday, March 03, 2010
8:59 AM
To: David Cramer;
Subject: RE: [docbook-apps]
variablelist styles
Hi
David,
In
the end, I managed to get my variablelists to appear on the same line with a
bold term, followed by the listitem paragraph.
However, I am now seeing
something very odd happening if the term element contains a guilabel or
guibutton tag. (Note that our guilabel/guibutton tags have no visual effect,
but are necessary for translation purposes)
If a
term has a guilabel/guibutton, an extra space appears before and after the
term, causing it to indent one space, and the runinhead to appear after a
space.
The
code I'm using for the XML is as follows:
<para>To show the margins</para>
<variablelist>
<varlistentry>
<term>
<guilabel>Test Label1</guilabel>
</term>
<listitem>
<para>The para to go with the
label1.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<guilabel>Test Label2</guilabel>
</term>
<listitem>
<para>The para to go with the
label2.</para>
</listitem>
</varlistentry>
<varlistentry><term><guilabel>Test Label3 on single
line</guilabel></term><listitem><para>Paragraph to go with label3</para></listitem></varlistentry>
</variablelist>
<para>Paragraph to show the
margins</para>
And
this is how it looks when rendered:
As
you can see, there is a slight space before the first 2 labels and another
before the full stops at the end (runinhead). The third line has been
modified in code so the term and its contents all appear on the same line.
Unfortunately, I cannot figure out why the output does this.
Is
anyone aware of what might cause this? We have not modified the guilabel or
guibutton tags from their default state. We are using version 1.74 of the
docbook styles.
Any
suggestions would be helpful.
Also, here is the code I
modified to get the variablelists to appear on the same
line.
<xsl:template
match="varlistentry"
mode="vl.as.blocks">
<xsl:variable
name="id">
<xsl:call-template
name="object.id"/>
</xsl:variable>
<fo:block
padding-top="2pt"
padding-bottom="2pt">
<fo:wrapper
font-weight="bold">
<xsl:apply-templates
select="term"/>
<xsl:value-of
select="$runinhead.default.title.end.punct"/>
</fo:wrapper>
<xsl:apply-templates
select="varlistentry/listitem"/>
</fo:block>
</xsl:template>
<!--This
template ensures that a fo:block is not added around the initial
paragraph-->
<!—-which
enables the term element to appear on the same line. Subsequent
paragraph-->
<!--entries
are rendered inside an fo:block as expected-->
<xsl:template
match="varlistentry/listitem/para">
<xsl:choose>
<xsl:when
test="not(preceding-sibling::*)">
<xsl:call-template
name="anchor"/>
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<fo:block>
<xsl:if
test="@role and $para.propagates.style != 0">
<xsl:apply-templates
select="." mode="class.attribute">
<xsl:with-param
name="class" select="@role"/>
</xsl:apply-templates>
</xsl:if>
<xsl:call-template
name="anchor"/>
<xsl:apply-templates/>
</fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Kind
Regards,
Laurie.
-----Original Message-----
From:
David Cramer [mailto:]
Sent: 11 February 2010
19:17
To: Laurie Burley
Subject: RE: [docbook-apps] variablelist
styles
Sure thing. Be sure to test with a variety of
legal
varlistentry/listitems and think what you might want
to have happen if
someone does something weird. E.g.
varlistentry/listitem/formalpara
(which would give you a runinhead, followed by a
runinhead!). Sometimes
I add <xsl:message terminate="yes">Some helpful
error message explaining
the unsupported constuct.</xsl:message> when I
find a construct I don't
want to support and don't want people to
use.
David
> -----Original Message-----
> From: Laurie Burley
[mailto:]
> Sent: Thursday, February 11, 2010 10:53
AM
> To: David Cramer;
; DeanNelson
> Subject: RE: [docbook-apps] variablelist
styles
>
> Thanks David,
>
> I also managed to get this working by creating a
new
> listitem/para template similar to the simpara..so
a <p> tag
> is not automatically applied to the listitem
paragraph if the
> first child is a para.
>
> I had a harder time with the FO output, but I
removed some of
> the blocks and replaced them with wrappers, and
it works as well.
>
> I will however, give your suggestion a try, just
in case it
> is cleaner ;).
>
> Kind Regards,
>
> Laurie.
>
>
>
> Laurie Burley
> Sr. Tech Comm Spc.
> Kofax U.K., Ltd.
>
> 201 Cambridge Science Park
> Milton Road, Cambridge
> CB4 0GZ
> United Kingdom
>
> Tel: +44 (0) 1223 226021
>
> -----Original Message-----
> From: David Cramer
[mailto:]
> Sent: 11 February 2010 15:49
> To: Laurie Burley;
; DeanNelson
> Subject: RE: [docbook-apps] variablelist
styles
>
>
> Hi Laurie,
> Ok, for html output the following customization
layer will do
> what you want. The parameter
variablelist.as.runinhead is set
> to 1 (and variablelist.as.table must also be 0 or
it will
> win) OR you can use the <?dbhtml
> list-presentation="runinhead"?> for individual
variablelists.
>
> One thing to note: this works fine for the normal
case where
> you have a varlistentry/lisitem/para (where para
is the first
> child of the listitem), but what if they do
> varlistentry/listitem/*[1], where the first child
of the
> listitem is not a para? That could end up looking
funny.
> Currently, I only do the runinhead thing if the
first child
> is a para. Otherwise, the normal formatting of
the elment
> happens. You'll probably want to adapt it to real
life, but
> this should get you started.
> Of course, you'll probably also want to do the
same thing for
> the fo xsls :-)
>
> This only overrides one template from the base
xsls (the one
> for variablelist). The other templates are new
additions.
>
> Good luck,
> David
>
> <xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xsl:import
>
href="http://docbook.sourceforge.net/release/xsl/current/html/
> docbook.xs
> l"/>
>
> <xsl:param
name="variablelist.as.table">0</xsl:param>
> <xsl:param
name="variablelist.as.runinhead">1</xsl:param>
>
> <!-- DWC: Modified to support runinhead style
-->
> <xsl:template
match="variablelist">
> <xsl:variable
name="pi-presentation">
> <xsl:call-template
name="dbhtml-attribute">
>
<xsl:with-param name="pis"
>
select="processing-instruction('dbhtml')"/>
>
<xsl:with-param name="attribute"
select="'list-presentation'"/>
>
</xsl:call-template>
> </xsl:variable>
>
> <xsl:variable
name="presentation">
>
<xsl:choose>
> <xsl:when
test="$pi-presentation != ''">
>
<xsl:value-of select="$pi-presentation"/>
>
</xsl:when>
> <xsl:when
test="$variablelist.as.table != 0">
>
<xsl:value-of select="'table'"/>
>
</xsl:when>
> <xsl:when
test="$variablelist.as.runinhead != 0">
>
<xsl:value-of select="'runinhead'"/>
>
</xsl:when>
>
<xsl:otherwise>
>
<xsl:value-of select="'list'"/>
>
</xsl:otherwise>
>
</xsl:choose>
> </xsl:variable>
>
> <xsl:variable
name="list-width">
> <xsl:call-template
name="dbhtml-attribute">
>
<xsl:with-param name="pis"
>
select="processing-instruction('dbhtml')"/>
>
<xsl:with-param name="attribute"
select="'list-width'"/>
>
</xsl:call-template>
> </xsl:variable>
>
> <xsl:variable
name="term-width">
> <xsl:call-template
name="dbhtml-attribute">
>
<xsl:with-param name="pis"
>
select="processing-instruction('dbhtml')"/>
>
<xsl:with-param name="attribute"
select="'term-width'"/>
>
</xsl:call-template>
> </xsl:variable>
>
> <xsl:variable
name="table-summary">
> <xsl:call-template
name="dbhtml-attribute">
>
<xsl:with-param name="pis"
>
select="processing-instruction('dbhtml')"/>
>
<xsl:with-param name="attribute"
select="'table-summary'"/>
>
</xsl:call-template>
> </xsl:variable>
>
> <div>
> <xsl:apply-templates
select="." mode="class.attribute"/>
> <xsl:call-template
name="anchor"/>
> <xsl:if
test="title">
>
<xsl:call-template name="formal.object.heading"/>
>
</xsl:if>
>
>
<xsl:choose>
> <xsl:when
test="$presentation = 'table'">
>
<!-- Preserve order of PIs and comments -->
>
<xsl:apply-templates select="*[not(self::varlistentry
> or
self::title
or self::titleabbrev)]
>
|comment()[not(preceding-sibling::varlistentry)]
>
|processing-instruction()[not(preceding-sibling::varlistentry)]"/>
>
<table border="0">
>
<xsl:if test="$list-width != ''">
>
<xsl:attribute name="width">
>
<xsl:value-of select="$list-width"/>
>
</xsl:attribute>
>
</xsl:if>
>
<xsl:if test="$table-summary != ''">
>
<xsl:attribute name="summary">
>
<xsl:value-of select="$table-summary"/>
>
</xsl:attribute>
>
</xsl:if>
>
<col align="left" valign="top">
>
<xsl:if test="$term-width != ''">
>
<xsl:attribute name="width">
>
<xsl:value-of select="$term-width"/>
>
</xsl:attribute>
>
</xsl:if>
>
</col>
>
<tbody>
>
<xsl:apply-templates mode="varlist-table"
> select="varlistentry
>
|comment()[preceding-sibling::varlistentry]
>
|processing-instruction()[preceding-sibling::varlistentry]"/>
>
</tbody>
>
</table>
>
</xsl:when>
>
<!-- DWC: Adding support for new presentation type -->
> <xsl:when
test="$presentation = 'runinhead'">
>
<!-- Preserve order of PIs and comments -->
>
<xsl:apply-templates select="*[not(self::varlistentry
> or
self::title
or self::titleabbrev)]
>
|comment()[not(preceding-sibling::varlistentry)]
>
|processing-instruction()[not(preceding-sibling::varlistentry)]"/>
>
<ul style="list-style-type: none">
>
<xsl:apply-templates select="varlistentry
>
|comment()[preceding-sibling::varlistentry]
>
|processing-instruction()[preceding-sibling::varlistentry]"
> mode="varlist-runinhead"/>
>
</ul>
>
</xsl:when>
>
<xsl:otherwise>
>
<!-- Preserve order of PIs and comments -->
>
<xsl:apply-templates select="*[not(self::varlistentry
> or
self::title
or self::titleabbrev)]
>
|comment()[not(preceding-sibling::varlistentry)]
>
|processing-instruction()[not(preceding-sibling::varlistentry)]"/>
>
<dl>
>
<xsl:apply-templates select="varlistentry
>
|comment()[preceding-sibling::varlistentry]
>
|processing-instruction()[preceding-sibling::varlistentry]"/>
>
</dl>
>
</xsl:otherwise>
>
</xsl:choose>
> </div>
> </xsl:template>
>
> <!-- DWC: added the following templates to add
support for
> runinhead varlist style --> <xsl:template
> match="varlistentry"
mode="varlist-runinhead">
> <li>
> <xsl:call-template
name="anchor"/>
>
<p>
>
<xsl:apply-templates select="term"
> mode="varlist-runinhead"/>
>
<xsl:apply-templates select="listitem/para[1]"
> mode="varlist-runinhead"/>
>
</p>
>
<xsl:apply-templates select="listitem"
> mode="varlist-runinhead"/>
> </li>
> </xsl:template>
>
> <xsl:template match="term"
mode="varlist-runinhead">
> <xsl:variable
name="titleStr">
>
<xsl:apply-templates/>
> </xsl:variable>
> <xsl:variable
name="lastChar">
> <xsl:if
test="$titleStr != ''">
>
<xsl:value-of
>
select="substring($titleStr,string-length($titleStr),1)"/>
>
</xsl:if>
> </xsl:variable>
>
> <b>
> <xsl:copy-of
select="$titleStr"/>
> <xsl:if
test="$lastChar !=
''
and
> not(contains($runinhead.title.end.punct,
$lastChar))">
>
<xsl:value-of
select="$runinhead.default.title.end.punct"/>
>
</xsl:if>
>
<xsl:text> </xsl:text>
> </b>
> </xsl:template>
>
> <xsl:template match="listitem"
mode="varlist-runinhead">
>
<xsl:choose>
>
<xsl:when test="*[1][self::para]">
>
<xsl:apply-templates select="*[position() >
1]"/>
>
</xsl:when>
>
<xsl:otherwise>
>
<xsl:apply-templates/>
>
</xsl:otherwise>
>
</xsl:choose>
> </xsl:template>
>
> <xsl:template match="para"
mode="varlist-runinhead">
>
<xsl:apply-templates/>
> </xsl:template>
>
> </xsl:stylesheet>
>
>
-------------------------------------------------
>
> This communication is only for the use of the
intended
> recipient. It may contain confidential or
proprietary
> information. If you are not the intended
recipient or have
> received this communication in error, please
notify the
> sender via phone and destroy this communication
immediately.
>
Laurie
Burley
Sr. Tech Comm Spc.
Kofax U.K., Ltd.
201
Cambridge Science Park
Milton Road, Cambridge
CB4 0GZ
United
Kingdom
Tel:
+44 (0) 1223 226021
This
communication is only for the use of the intended recipient. It may contain
confidential or proprietary information. If you are not the intended
recipient or have received this communication in error, please notify the
sender via phone and destroy this communication immediately.
Next in thread →
Next in month →