Next in thread → Next in month →

Re: [docbook-apps] variablelist styles

From
"Cob Rtayton"
Date
2010-03-05T18:57:42+00:00
ID
009201cabc95$b5bbe760$6600a8c0@pazu
Thread
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>&#160;</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() &gt; 
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 →