Re: [docbook-apps] xrefs to <title> elements don't work

From
Bob Stayton <>
Date
2013-04-05T16:18:05+00:00
ID
0B34779A2C3A492FBB55DDD0F9497A9C@totoro
Thread
Re: [docbook-apps] xrefs to <title> elements don't work
Hi Eric,

Actually, creating an xref to a title used to work in the 
stylesheets.  Currently it gets the generated text right, but the link is 
to the id of the title element, and most title elements do not output an @id 
attribute, so the link fails.   It seems this feature was broken some 
time ago when the xref templates were rewritten to support universal linking in 
DocBook 5.

 

This customization of the template named 'simple.xlink' from 
fo/inline.xsl fixes the id problem.  It only corrects the problem for 
@linkend references, not for @xlink:href references used in universal 
linking, but it should suffice for your needs.  Search for 
'linkend.candidate' to see where I made the changes.

 

 

<xsl:template name="simple.xlink">
  
<xsl:param name="node" select="."/>
  <xsl:param 
name="content">
    <xsl:apply-templates/>
  
</xsl:param>
  <xsl:param name="linkend.candidate" select="$node/@linkend"/>
  <xsl:param 
name="xhref" select="$node/@xlink:href"/>

 

  <xsl:choose>
    <xsl:when 
test="$xhref
                    
and (not($node/@xlink:type) or 

                         
$node/@xlink:type='simple')">

 

      <!-- Is it a local idref? 
-->
      <xsl:variable 
name="is.idref">
        
<xsl:choose>
          
<!-- if the href starts with # and does not contain an "(" 
-->
          <!-- or if 
the href starts with #xpointer(id(, it's just an ID 
-->
          <xsl:when 
test="starts-with($xhref,'#')
                          
and 
(not(contains($xhref,'&#40;'))
                          
or 
starts-with($xhref,
                                     
'#xpointer&#40;id&#40;'))">1</xsl:when>
          
<xsl:otherwise>0</xsl:otherwise>
        
</xsl:choose>
      
</xsl:variable>

 

      <!-- Is it an olink ? 
-->
      <xsl:variable 
name="is.olink">
        
<xsl:choose>
          
<!-- If xlink:role="http://docbook.org/xlink/role/olink" 
-->
          <!-- and if 
the href contains # 
-->
          <xsl:when 
test="contains($xhref,'#') 
and
               
@xlink:role = 
$xolink.role">1</xsl:when>
          
<xsl:otherwise>0</xsl:otherwise>
        
</xsl:choose>
      
</xsl:variable>

 

      
<xsl:choose>
        <xsl:when 
test="$is.olink = 
1">
          
<xsl:call-template 
name="olink">
            
<xsl:with-param name="content" 
select="$content"/>
          
</xsl:call-template>
        
</xsl:when>

 

        <xsl:when 
test="$is.idref = 1">

 

          
<xsl:variable 
name="idref">
            
<xsl:call-template 
name="xpointer.idref">
              
<xsl:with-param name="xpointer" 
select="$xhref"/>
            
</xsl:call-template>
          
</xsl:variable>

 

          
<xsl:variable name="targets" 
select="key('id',$idref)"/>
          
<xsl:variable name="target" select="$targets[1]"/>

 

          
<xsl:call-template 
name="check.id.unique">
            
<xsl:with-param name="linkend" 
select="$idref"/>
          
</xsl:call-template>

 

          
<xsl:choose>
            
<xsl:when test="count($target) = 
0">
              
<xsl:message>
                
<xsl:text>XLink to nonexistent id: 
</xsl:text>
                
<xsl:value-of 
select="$idref"/>
              
</xsl:message>
              
<xsl:copy-of 
select="$content"/>
            
</xsl:when>

 

            
<xsl:otherwise>
              
<fo:basic-link 
internal-destination="{$idref}">
                
<xsl:apply-templates select="." 
mode="simple.xlink.properties"/>
                
<xsl:copy-of 
select="$content"/>
              
</fo:basic-link>
            
</xsl:otherwise>
          
</xsl:choose>
        
</xsl:when>

 

        <!-- otherwise 
it's a URI -->
        
<xsl:otherwise>
          
<fo:basic-link 
external-destination="url({$xhref})">
            
<xsl:apply-templates select="." 
mode="simple.xlink.properties"/>
            
<xsl:copy-of 
select="$content"/>
          
</fo:basic-link>
          
<!-- * Call the template for determining whether the URL for this 
-->
          <!-- * 
hyperlink is displayed, and how to display it (either inline or 
-->
          <!-- * as a 
numbered footnote). 
-->
          
<xsl:call-template 
name="hyperlink.url.display">
            
<xsl:with-param name="url" 
select="$xhref"/>
          
</xsl:call-template>
        
</xsl:otherwise>
      
</xsl:choose>
    </xsl:when>

 

    <xsl:when 
test="$linkend.candidate">
      <xsl:variable 
name="targets.candidate" 
select="key('id',$linkend.candidate)"/>
      
<xsl:variable name="target.candidate" 
select="$targets.candidate[1]"/>

 

      <xsl:variable 
name="target.id">
        
<xsl:choose>
          
<xsl:when test="$target.candidate/self::title and 

                          
$target.candidate/parent::*/@id">
            
<xsl:value-of 
select="$target.candidate/parent::*/@id"/>
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="$target.candidate/@id"/>
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:variable>

 

      <xsl:variable name="targets" 
select="key('id',$target.id)"/>
      
<xsl:variable name="target" 
select="$targets[1]"/>
      <xsl:variable 
name="linkend" select="$target/@id"/>

 

      <xsl:call-template 
name="check.id.unique">
        
<xsl:with-param name="linkend" 
select="$linkend"/>
      
</xsl:call-template>

 

      
<xsl:choose>
        <xsl:when 
test="count($target) = 
0">
          
<xsl:message>
            
<xsl:text>XLink to nonexistent id: 
</xsl:text>
            
<xsl:value-of 
select="$linkend"/>
          
</xsl:message>
          
<xsl:copy-of 
select="$content"/>
        
</xsl:when>

 

        
<xsl:otherwise>
          
<fo:basic-link 
internal-destination="{$linkend}">
            
<xsl:apply-templates select="." 
mode="simple.xlink.properties"/>
            
<xsl:copy-of 
select="$content"/>
          
</fo:basic-link>
        
</xsl:otherwise>
      
</xsl:choose>
    </xsl:when>

 

    
<xsl:otherwise>
      <xsl:copy-of 
select="$content"/>
    </xsl:otherwise>
  
</xsl:choose>
</xsl:template>

 

</xsl:stylesheet>

Bob Stayton
Sagehill Enterprises


From: Eric Nordlund 

Sent: Thursday, April 04, 2013 6:00 PM

To:  

Subject: [docbook-apps] xrefs to <title> elements don't 
work

My company has a hundred or so books that were authored with 
Arbortext?s graphic XML editor. I?m having a problem processing these books with 
XSL-FO because so many of the xrefs in these books are to title elements instead 
of the parent procedure, section, example, table, etc., elements.

 

Is there a way to make these work in the XSL-FO output? I was 
thinking I could have a template that could recognize when an xref/@linkend 
pointed to the id of a title and then change the linkend to the id of the 
title?s parent element, but I don?t really know how to do that.

 

Is there another way to do what I need to do?

 

Eric Nordlund

Customer 
Documentation and Training

Cray 
Inc.

901 5th 
Ave

Seattle, WA 
98164

(206)701-2232