Creating Custom Topic Types

THESE PAGES ARE STILL UNDER CONSTRUCTION AND DO NOT NECESSARELY REFLECT THE CURRENT VERSION OF TÓPICO

Any publication can benefit from using different topic types, be it a tutorial, a FAQ page, and article, a recepie or anything meaningful piece of content that is relevant to your need. A specialised topic type is typically used with a custom transformation template that takes advantage of it's specific structure. Some custom CSS styles might also be used to format the content of the new topic type.

As an example, this topic introduces the FAQ page from this User Guide.

Creating the FAQ topic type

Basically, the default template was copied and saved as a new template. The template name is topic_faq.xml. The body element default content was then set as follow.

HTML
			<body>
			<div id="faq">
			<div class="section">
			<p class="title">[section title]</p>
			<div class="question">
			<p class="question">[question]</p>
			<div class="answer">
			<p>[answer]</p>
			<p>[answer]</p>
			</div>
			</div>
			<div class="question">
			<p class="question">[question]</p>
			<div class="answer">
			<p>[answer]</p>
			<p>[answer]</p>
			</div>
			</div>
			<div class="question">
			<p class="question">[question]</p>
			<div class="answer">
			<p>[answer]</p>
			<p>[answer]</p>
			</div>
			</div>
			</div>
			...
			</div>
			</body>
		

About the FAQ topic type

The idea behind this template is to have sections of questions (with answers) and be able to create and index at the top of the published page with the question as the text linking to each answer further down on the page. This approach can make a rather long FAQ page much more usable. Adding interactivity would also be possible but a bit out of scope here.

The FAQ structure

The FAQ topic can have a standard XHTML intro but will contain this markup somewhere in the document body.

HTML
			<div id="faq">
			<div class="section">
			<p class="title">...</p>
			<div class="question">
			<p class="question">...</p>
			<div class="answer">
			<p>...</p><p>...</p>...
			</div>
			</div>
			<div class="question">
			<p class="question">...</p>
			<div class="answer">
			<p>...</p><p>...</p>...
			</div>
			</div>
			...
			</div>
			...
			</div>
		

The above markup reads as follow:

  • An outer <div class="faq"> element wraps the whole FAQ topic type
  • Then sections are created with <div class="section">
  • Inside each section, there is ...
    • A section title using <p class="title">[section title]</p>
    • As many question as needed with <div class="question">
    • Each question is composed of ...
      • A question paragraph with <p class="question">[question]</p>
      • An answer with paragraphs using <div class="answer"> and <p>[answer]</p>...

The FAQ template

A topic based on this model is also assigned a specific XSL template to take advantage of the structure. Here's what this template looks like.

XSLT
			<?xml version="1.0"?>
			<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xhtml="http://www.w3.org/1999/xhtml">
			<!-- templates parameters -->
			<xsl:import href="template_user_guide.xsl"/>
			<!--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
			<!-- faq template -->
			<xsl:template match="xhtml:div[@id='faq']" mode="import">
			<a name="top"/>
			<div id="faq">
			<!-- questions list with links -->
			<xsl:apply-templates select="//xhtml:div[@class='section']" mode="index"/>
			<!-- separator -->
			<div align="center" style="font-size:24pt; font-weight:bold;">. . .</div>
			<!-- questions details -->
			<xsl:apply-templates select="//xhtml:div[@class='section']" mode="details"/>
			</div>
			</xsl:template>
			<!--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
			<!-- a bulleted list with links to individual questions -->
			<xsl:template match="xhtml:div[@class='section']" mode="index">
			<xsl:param name="catpos" select="position()"/>
			<div class="section_faq_index">
			<p class="section_faq_index_title">
			<span class="section_faq_index_title">
			<xsl:value-of select="xhtml:p[@class='title']"/>
			</span>
			</p>
			<ul>
			<xsl:for-each select="xhtml:div[@class='question']">
			<li class="question">
			<a>
			<xsl:attribute name="href">#<xsl:value-of select="generate-id()"/></xsl:attribute>
			<!-- write the question as the link text -->
			<xsl:value-of select="xhtml:p[@class='question']"/>
			</a>
			</li>
			</xsl:for-each>
			</ul>
			</div>
			</xsl:template>
			<!--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
			<!-- details of each question -->
			<xsl:template match="xhtml:div[@class='section']" mode="details">
			<xsl:variable name="catpos" select="position()"/>
			<div class="section">
			<p class="section_title">
			<span class="section_title">
			<xsl:value-of select="xhtml:p[@class='title']"/>
			</span>
			</p>
			<xsl:for-each select="xhtml:div[@class='question']">
			<div class="question">
			<!-- get the id from the qitem attribute using the Attribute Value Template -->
			<a name="{generate-id()}"/>
			<!-- write the question -->
			<p class="question">
			<xsl:value-of select="xhtml:p[@class='question']"/>
			<a href="#top">
			<sup> ...top</sup>
			</a>
			</p>
			<!-- write the answer -->
			<div class="answer">
			<xsl:copy-of select="xhtml:div[@class='answer']/*"/>
			</div>
			</div>
			</xsl:for-each>
			</div>
			</xsl:template>
			</xsl:stylesheet>
		

The above template can be read as follow:

  • Import the base template first with <xsl:import href="template_user_guide.xsl"/>
  • Create a wrapper div with the first template:
    <xsl:template match="xhtml:div[@id='faq']" mode="import">
    This template calls the other two with the appropriate mode.
  • Create the table of content with this template:
    <xsl:template match="xhtml:div[@class='section']" mode="index">
    Note the "index" mode of the template.
  • Create each section questions and answers details with this template:
    <xsl:template match="xhtml:div[@class='section']" mode="details">
    Note the "details" mode of the template.

Using a custom template for this topic type makes the published page much easier to navigate for your users.

The FAQ styles

It's also a best practice to assign specific styles to our new topic type publication. Here's what the stylesheet looks like.

CSS
			div#faq {}
			div#faq div.section_faq_index {margin-top:8px; }
			div#faq div.section_faq_index p.section_faq_index_title {color:#004400; font-family:Tahoma, Helvetica, sans-serif; font-weight:bold; font-size:1.2em; padding-bottom:0px; border-bottom:1px solid black;}
			div#faq div.section_faq_index span.section_faq_index_title {background-color:#CEEEAE; padding: 4px 4px 0px 4px; margin-bottom:0px; border: 1px solid black;}
			div#faq div.section_faq_index ul {}
			div#faq div.section {margin-top:12px; }
			div#faq div.section p.section_title {color:#004400; font-family:Tahoma, Helvetica, sans-serif; font-weight:bold; font-size:1.2em; padding-bottom:0px; border-bottom:1px solid black;}
			div#faq div.section span.section_title {background-color:#CEEEAE; padding: 4px 4px 0px 4px; margin-bottom:0px; border: 1px solid black;}
			div#faq div.section div.question {}
			div#faq div.section div.question p.question {font-weight:bold;}
			div#faq div.section div.question div.answer {margin-left:16px; margin-right:16px;}
			div#faq div.section div.question div.answer p {font-style:italic;}
			div#faq div.section div.question div.answer ul li, div.question div.answer ol li { }
		

The FAQ Schematron

The following Schematron schema can then be used to inform the user if the document ever becomes invalid.

XML
			<?xml version="1.0" encoding="UTF-8"?>
			<schema xmlns="http://www.ascc.net/xml/schematron">
			<title>FAQ</title>
			<ns uri="http://www.w3.org/1999/xhtml" prefix="xhtml"/>
			<pattern name="Default Pattern">
			<rule context="/">
			<assert test="xhtml:html">The root of this document should be html</assert>
			<report test="xhtml:html">The root of this document is html</report>
			</rule>
			<rule context="//xhtml:body">
			<assert test="xhtml:div[@class='faq']">The body needs to have at least one div class="faq".</assert>
			<report test="xhtml:div[@class='faq']">The body has at least one div class "faq".</report>
			</rule>
			<rule context="//xhtml:div[@class='faq']">
			<assert test="xhtml:div[@class='section']">The div class="faq" needs to have at least one div class="section".</assert>
			<report test="xhtml:div[@class='section']">The div class="faq" has at least one div class "section".</report>
			<assert
			test="count(//xhtml:div[@class='question']) &gt;= count(//xhtml:div[@class='section']) "
			>Each div class="faq" needs an equal or a greater number of div class="question" than div class="section".</assert>
			<report
			test="count(//xhtml:div[@class='question']) &gt;= count(//xhtml:div[@class='section']) "
			>Each div class="faq" has an equal or greater number of div class="question" than div class="section".</report>
			</rule>
			<rule context="//xhtml:div[@class='section']">
			<assert test="xhtml:p[@class='title']">Each div class="section" needs a p class="title" </assert>
			<report test="xhtml:p[@class='title']">Each div class="section" has a p class="title" </report>
			<assert test="xhtml:div[@class='question']">Each div class="section" needs at least a div class="question" </assert>
			<report test="xhtml:div[@class='question']">Each div class="section" has at least a div class="question" </report>
			<assert test="count(//xhtml:p[@class='question']) = count(//xhtml:div[@class='answer']) "
			>This topic needs the same number of p class="question" and div class="answer".</assert>
			<report test="count(//xhtml:p[@class='question']) = count(//xhtml:div[@class='answer']) "
			>This topic has the same number of p class="question" and div class="answer".</report>
			</rule>
			<rule context="//xhtml:div[@class='question']">
			<assert test="xhtml:p[@class='question']">Each div class="question"" needs a p class="question"</assert>
			<report test="xhtml:p[@class='question']">Each div class="question"" has a p class="question"</report>
			<assert test="xhtml:div[@class='answer']">Each div class="question"" needs a div class="answer" </assert>
			<report test="xhtml:div[@class='answer']">Each div class="question"" has a div class="answer"</report>
			</rule>
			</pattern>
			</schema>
		

To learn more about validating a custom topic type, check out Validating a topic using Schematron.

THESE PAGES ARE STILL UNDER CONSTRUCTION AND DO NOT NECESSARELY REFLECT THE CURRENT VERSION OF TÓPICO

112 / 194