Provide openstack-dn2osdbk

This tool converts docutils native XML to docbook. The conversion is
done using XSLT, with some custom XML treatment.

The XSL source is a slightly modified version of Dn2dbk written by Éric
Bellot (http://ebellot.chez.com/dn2dbk/index.htm).

Modify doctest to check and build the HOT guide.

Implements: blueprint heat-templates

Change-Id: If866a5ffe19165c38981493684de550e0df0e36d
This commit is contained in:
Gauvain Pocentek 2014-07-18 15:44:18 +02:00
parent de741f0a2e
commit bb6df9a0a9
5 changed files with 1040 additions and 0 deletions

View File

@ -102,6 +102,8 @@ Release notes
* Added support for *-manage CLI doc generation. * Added support for *-manage CLI doc generation.
* Various smaller fixes and improvements. * Various smaller fixes and improvements.
* ``openstack-dn2osdbk``: Converts Docutils Native XML to docbook.
* ``openstack-doc-test``: Handle the upcoming HOT guide.
0.16.1 0.16.1
------ ------

225
os_doc_tools/dn2osdbk.py Normal file
View File

@ -0,0 +1,225 @@
#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import glob
import os
import sys
from lxml import etree
OS_DOC_TOOLS_DIR = os.path.dirname(__file__)
DN2DBK = os.path.join(OS_DOC_TOOLS_DIR, 'resources', 'dn2osdbk.xsl')
XML_NS = '{http://www.w3.org/XML/1998/namespace}'
TRANSFORMERS = {'chapter': 'ChapterTransformer', 'book': 'BookTransformer'}
class XMLFileTransformer(object):
"""Transform a single DN XML file to docbook.
Call the transform() method to generate the docbook output.
"""
def __init__(self, source_file, toplevel='chapter'):
"""Initialize an instance.
:param source_file: The path to the source DN XML file.
:param toplevel: The top level tag of the generated docbook ('book' or
'chapter').
"""
self.source_file = source_file
self.toplevel = toplevel
basename = os.path.basename(self.source_file)
self.basename = os.path.splitext(basename)[0]
self.xslt_file = DN2DBK
def _xslt_transform(self, xml):
with open(self.xslt_file) as fd:
xslt = fd.read()
xslt_root = etree.XML(xslt)
transform = etree.XSLT(xslt_root)
return transform(xml)
def _custom_transform(self, tree):
# Set the correct root tag
root = tree.getroot()
root.tag = '{http://docbook.org/ns/docbook}%s' % self.toplevel
# Add a comment to warn that the file is autogenerated
comment = etree.Comment("WARNING: This file is automatically "
"generated. Do not edit it.")
root.insert(0, comment)
for item in tree.iter():
# Find tags with an 'id' attribute, and prefix its value with the
# basename of the file being processed. This avoids id conflicts
# when working with multiple source files.
id_attrib = '%sid' % XML_NS
id = item.get(id_attrib)
if id is not None:
id = id.split(' ')[-1]
id = "%s_%s" % (self.basename, id)
item.attrib[id_attrib] = id
# Same for the linkend attribute.
linkend = item.get('linkend')
if linkend is not None:
item.attrib['linkend'] = "%s_%s" % (self.basename, linkend)
return tree
def transform(self):
"""Generate the docbook XML."""
with open(self.source_file) as fd:
source_xml = fd.read()
source_doc = etree.XML(source_xml)
result_tree = self._xslt_transform(source_doc)
result_tree = self._custom_transform(result_tree)
return etree.tostring(result_tree, pretty_print=True,
xml_declaration=True, encoding="UTF-8")
class BaseFolderTransformer(object):
"""Base class for generating docbook from an DN XML source dir."""
file_toplevel = 'section'
def __init__(self, source_dir, output_dir, index='index.xml'):
"""Initialize an instance.
:param source_dir: The DN XML source directory.
:param output_dir: The directory in which docbook files will be stored.
This directory is created if it doesn't exist.
:param index: The name of the index file in the source dir.
"""
self.source_dir = source_dir
self.output_dir = output_dir
self.index = index
self.includes = []
self.title = None
self.parse_index()
if not os.path.isdir(self.output_dir):
os.makedirs(self.output_dir)
def parse_index(self):
"""Generates part of the docbook index from the DN XML index.
The full index is generated in the write_index method.
"""
src = os.path.join(self.source_dir, 'index.xml')
src_xml = etree.XML(open(src).read())
for reference in src_xml.iter('reference'):
if '#' in reference.get('refuri'):
continue
self.includes.append("%s_%s.xml" % (self.file_toplevel,
reference.get('refuri')))
self.title = src_xml.find('section/title').text
def write_index(self):
"""Write the index file.
This method must be implemented by subclasses.
"""
raise NotImplementedError
def transform(self):
"""Perform the actual conversion."""
files = glob.glob(os.path.join(self.source_dir, '*.xml'))
for src in files:
if src.endswith('/index.xml'):
continue
basename = '%s_%s' % (self.file_toplevel, os.path.basename(src))
output_file = os.path.join(self.output_dir, basename)
transformer = XMLFileTransformer(src, self.file_toplevel)
xml = transformer.transform()
open(output_file, 'w').write(xml)
self.write_index()
class BookTransformer(BaseFolderTransformer):
"""Create a docbook book."""
file_toplevel = 'chapter'
def write_index(self):
output_file = os.path.join(self.output_dir, 'index.xml')
xml_id = self.title.lower().replace(' ', '-')
includes = "\n ".join([
'<xi:include href="%s"/>' % i for i in self.includes])
output = '''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book [
]>
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="5.0"
xml:id="%(xml_id)s">
<!-- WARNING: This file is automatically generated. Do not edit it. -->
<title>%(title)s</title>
%(includes)s
</book>''' % {'xml_id': xml_id, 'title': self.title, 'includes': includes}
open(output_file, 'w').write(output)
class ChapterTransformer(BaseFolderTransformer):
"""Create a docbook chapter."""
file_toplevel = 'section'
def write_index(self):
output_file = os.path.join(self.output_dir, 'index.xml')
xml_id = self.title.lower().replace(' ', '-')
includes = "\n ".join([
'<xi:include href="%s"/>' % i for i in self.includes])
output = '''<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="5.0"
xml:id="%(xml_id)s">
<!-- WARNING: This file is automatically generated. Do not edit it. -->
<title>%(title)</title>
%(includes)s
</chapter>''' % {'xml_id': xml_id, 'title': self.title, 'includes': includes}
open(output_file, 'w').write(output)
def main():
parser = argparse.ArgumentParser(description="Generate docbook from "
"DocUtils Native XML format")
parser.add_argument('source', help='Source directory.')
parser.add_argument('output', help='Output file.')
parser.add_argument('--toplevel', help='Toplevel flag.',
choices=['book', 'chapter'],
default='chapter')
args = parser.parse_args()
cls = globals()[TRANSFORMERS[args.toplevel]]
transformer = cls(args.source, args.output)
sys.exit(transformer.transform())
if __name__ == "__main__":
main()

View File

@ -798,6 +798,28 @@ def build_book(book, publish_path, log_path):
) )
# Success # Success
base_book = "install-guide (for Debian, Fedora, openSUSE, Ubuntu)" base_book = "install-guide (for Debian, Fedora, openSUSE, Ubuntu)"
# HOT template guide
elif base_book == 'hot-guide':
# Make sure that the build dir is clean
if os.path.isdir('build'):
shutil.rmtree('build')
# Generate the DN XML
output = subprocess.check_output(
["make", "xml"],
stderr=subprocess.STDOUT
)
out_file.write(output)
# Generate the docbook book
output = subprocess.check_output(
["openstack-dn2osdbk", "build/xml", "build/docbook",
"--toplevel", "book"],
stderr=subprocess.STDOUT
)
out_file.write(output)
output = subprocess.check_output(
["mvn", "generate-sources", comments, release, "-B"],
stderr=subprocess.STDOUT
)
# Repository: identity-api # Repository: identity-api
elif (cfg.CONF.repo_name == "identity-api" elif (cfg.CONF.repo_name == "identity-api"
and book.endswith("v3")): and book.endswith("v3")):
@ -918,6 +940,9 @@ def find_affected_books(rootdir, book_exceptions, file_exceptions,
f_abs = os.path.abspath(os.path.join(root, f)) f_abs = os.path.abspath(os.path.join(root, f))
if is_book_master(f_base): if is_book_master(f_base):
book_bk[f_abs] = book_root book_bk[f_abs] = book_root
if "doc/hot-guide/" in f_abs:
affected_books.add('hot-guide')
continue
if not is_testable_xml_file(f, file_exceptions): if not is_testable_xml_file(f, file_exceptions):
continue continue

View File

@ -0,0 +1,787 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
#=======
# Dn2dbk
#=======
#
# :author: Eric Bellot
# :email: ebellot@netcourrier.com
# :date: 2003-02-27
# :version: 0.3.1
# :Copyright: Copyright© 2003, Eric Bellot
#
# This script is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This script is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<xsl:stylesheet version="1.1"
xmlns="http://docbook.org/ns/docbook"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/document/section">
<toplevel xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">
<xsl:attribute name="xml:id">
<xsl:value-of select="translate(@ids,':','_')"/>
</xsl:attribute>
<xsl:apply-templates/>
</toplevel>
</xsl:template>
<!--
ARTICLEINFO
-->
<xsl:template name="articleinfo">
<articleinfo>
<xsl:apply-templates select="/document/title" mode="articleinfo"/>
<xsl:apply-templates select="/document/docinfo" mode="articleinfo"/>
<xsl:apply-templates select="/document/topic[@class='abstract']"
mode="articleinfo"/>
<xsl:apply-templates select="/document/topic[@class='dedication']"
mode="articleinfo"/>
</articleinfo>
</xsl:template>
<xsl:template match="/document/title"/>
<xsl:template match="title" mode="articleinfo">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
<xsl:template match="docinfo"/>
<xsl:template match="docinfo" mode="articleinfo">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="authors">
<authorgroup>
<xsl:apply-templates/>
</authorgroup>
</xsl:template>
<xsl:template match="author">
<author>
<othername>
<xsl:apply-templates/>
</othername>
<xsl:call-template name="affiliation"/>
</author>
</xsl:template>
<xsl:template match="contact/reference"/>
<xsl:template match="contact">
<bibliomisc>
<email>
<xsl:value-of select="normalize-space(string(reference))"/>
</email>
</bibliomisc>
</xsl:template>
<xsl:template match="date">
<pubdate>
<xsl:apply-templates/>
</pubdate>
</xsl:template>
<xsl:template match="/document/topic[@class='abstract']"/>
<xsl:template match="topic" mode="articleinfo">
<xsl:if test="@class='abstract'">
<abstract>
<xsl:apply-templates select="paragraph"/>
</abstract>
</xsl:if>
</xsl:template>
<xsl:template name="affiliation">
<xsl:if test="../organization or normalize-space(
string(../field/field_name))='jobtitle'">
<affiliation>
<xsl:apply-templates select="../field
[normalize-space(field_name)='jobtitle']"
mode="articleinfo"/>
<xsl:apply-templates select="../organization"
mode="articleinfo"/>
</affiliation>
</xsl:if>
</xsl:template>
<xsl:template match="field[normalize-space(field_name)='jobtitle']"/>
<xsl:template match="field[normalize-space(field_name)='jobtitle']"
mode="articleinfo">
<jobtitle>
<xsl:apply-templates select="field_body/paragraph[1]/node()"/>
</jobtitle>
</xsl:template>
<xsl:template match="organization"/>
<xsl:template match="organization" mode="articleinfo">
<orgname>
<xsl:apply-templates/>
</orgname>
</xsl:template>
<xsl:template match="status"/>
<xsl:template match="version">
<releaseinfo>
<xsl:apply-templates/>
</releaseinfo>
</xsl:template>
<xsl:template match="copyright">
<xsl:param name="ct" select="normalize-space(string(.))"/>
<xsl:if test="normalize-space(substring-before($ct,'©'))='Copyright'
or normalize-space(substring-before($ct,'©'))='copyright'">
<copyright>
<year>
<xsl:value-of
select="normalize-space(substring-before(substring-after($ct,'©'),','))"/>
</year>
<holder>
<xsl:value-of
select="normalize-space(substring-after(substring-after($ct,'©'),','))"/>
</holder>
</copyright>
</xsl:if>
</xsl:template>
<xsl:template match="address">
<address>
<xsl:apply-templates/>
</address>
</xsl:template>
<xsl:template match="docinfo/field">
<xsl:choose>
<xsl:when test="normalize-space(field_name)='legalnotice' or
normalize-space(field_name)='Legalnotice'">
<legalnotice>
<xsl:apply-templates select="field_body"/>
</legalnotice>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="notags">
<xsl:apply-templates mode="notags"/>
</xsl:template>
<xsl:template match="topic[@class='dedication']"/>
<xsl:template match="topic[@class='dedication']" mode="articleinfo">
<dedication>
<xsl:apply-templates/>
</dedication>
</xsl:template>
<!-- TOC -->
<xsl:template match="topic[@class='contents']">
<toc>
<xsl:apply-templates select="title" mode="titletoc"/>
<tocchap>
<xsl:apply-templates mode="toc"/>
</tocchap></toc>
</xsl:template>
<xsl:template match="title" mode="toc"/>
<xsl:template match="title" mode="titletoc">
<xsl:apply-templates select="."/>
</xsl:template>
<xsl:template match="bullet_list" mode="toc">
<xsl:param name="level" select="count(ancestor::bullet_list)"/>
<xsl:choose>
<xsl:when test="$level=0">
<xsl:apply-templates mode="toc"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{concat('toclevel',$level)}">
<xsl:apply-templates mode="toc"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="list_item" mode="toc">
<tocentry>
<xsl:attribute name="xml:id">
<xsl:value-of select="paragraph/reference/@id"/>
</xsl:attribute>
<xsl:attribute name="linkend">
<xsl:value-of select="paragraph/reference/@refid"/>
</xsl:attribute>
<xsl:apply-templates select="paragraph/reference/node()" mode="toc"/>
</tocentry>
<xsl:apply-templates select="bullet_list" mode="toc"/>
</xsl:template>
<!--
BODY
-->
<xsl:template match="section">
<section>
<xsl:attribute name="xml:id">
<xsl:value-of select="translate(@ids,':','_')"/>
</xsl:attribute>
<xsl:if test="count(ancestor::section)=1">
<xsl:processing-instruction name="dbhtml stop-chunking"/>
</xsl:if>
<xsl:apply-templates/>
</section>
</xsl:template>
<xsl:template match="title">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
<xsl:template match="paragraph|compact_paragraph|inline|rubric">
<para>
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="literal_block|doctest_block">
<programlisting>
<xsl:if test="@language != ''">
<xsl:attribute name="language">
<xsl:value-of select="@language"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="name(current())='doctest_block'">
<xsl:attribute name="role">
<xsl:value-of select="'doctest'"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates /></programlisting>
</xsl:template>
<xsl:template match="line_block">
<literallayout>
<xsl:apply-templates />
</literallayout>
</xsl:template>
<xsl:template match="block_quote">
<blockquote>
<xsl:apply-templates/>
</blockquote>
</xsl:template>
<xsl:template match="bullet_list">
<itemizedlist>
<xsl:if test="@mark">
<xsl:attribute name="mark">
<xsl:value-of select="@bullet"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</itemizedlist>
</xsl:template>
<xsl:template match="enumerated_list">
<orderedlist>
<xsl:attribute name="numeration">
<xsl:value-of select="@enumtype"/>
</xsl:attribute>
<xsl:apply-templates/>
</orderedlist>
</xsl:template>
<xsl:template match="definition_list|option_list">
<xsl:param name="role" select="name(current())"/>
<variablelist>
<xsl:attribute name="role">
<xsl:value-of select="$role"/>
</xsl:attribute>
<xsl:apply-templates/>
</variablelist>
</xsl:template>
<xsl:template match="definition_list_item|option_list_item">
<varlistentry>
<xsl:apply-templates/>
</varlistentry>
</xsl:template>
<xsl:template match="term|option_group">
<term>
<xsl:if test="following-sibling::classifier">
<xsl:attribute name="role">
<xsl:value-of select="following-sibling::classifier"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</term>
</xsl:template>
<xsl:template match="classifier"/>
<xsl:template match="option">
<option>
<xsl:apply-templates/>
</option>
<xsl:if test="following-sibling::option">
<xsl:value-of select="', '"/>
</xsl:if>
</xsl:template>
<xsl:template match="option_string">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="option_argument">
<xsl:if test="@delimiter">
<xsl:value-of select="@delimiter"/>
</xsl:if>
<replaceable>
<xsl:apply-templates/>
</replaceable>
</xsl:template>
<xsl:template match="list_item|definition|description">
<xsl:choose>
<xsl:when test="normalize-space(.)">
<listitem>
<xsl:apply-templates/>
</listitem>
</xsl:when>
<xsl:otherwise>
<listitem><para>???</para></listitem>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="field_name[not(ancestor::docinfo)]">
<xsl:choose>
<xsl:when test="normalize-space(string(.))='attribution' or
normalize-space(string(.))='Attribution'">
<attribution>
<xsl:apply-templates select="../field_body" mode="attribution"/>
</attribution>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="field_body[not(ancestor::docinfo)]"/>
<xsl:template match="field_body" mode="attribution">
<xsl:apply-templates select="paragraph[1]/*|paragraph[1]/text()"/>
</xsl:template>
<xsl:template match="paragraph[interpreted/@role='title']">
<xsl:apply-templates/>
</xsl:template>
<!--
INLINETAGS
-->
<xsl:template match="emphasis">
<emphasis>
<xsl:apply-templates/>
</emphasis>
</xsl:template>
<xsl:template match="strong">
<emphasis>
<xsl:attribute name="role">
<xsl:value-of select="'strong'"/>
</xsl:attribute>
<xsl:apply-templates/>
</emphasis>
</xsl:template>
<xsl:template match="literal">
<literal>
<xsl:apply-templates/>
</literal>
</xsl:template>
<xsl:template match="title_reference">
<citetitle>
<xsl:apply-templates/>
</citetitle>
</xsl:template>
<xsl:template match="raw">
<xsl:if test="@format='docbook'">
<xsl:value-of disable-output-escaping="yes" select="."/>
</xsl:if>
</xsl:template>
<!--
BIBLIOGRAPHY
-->
<xsl:template match="citation_reference">
<xref>
<xsl:attribute name="linkend">
<xsl:value-of select="@refid"/>
</xsl:attribute>
<xsl:attribute name="xml:id">
<xsl:value-of select="@id"/>
</xsl:attribute>
</xref>
</xsl:template>
<xsl:template match="citation"/>
<xsl:template name="bibliography">
<xsl:if test="//citation">
<bibliography>
<xsl:for-each select="//citation">
<xsl:apply-templates select="." mode="biblio"/>
</xsl:for-each>
</bibliography>
</xsl:if>
</xsl:template>
<xsl:template match="citation" mode="biblio">
<xsl:param name="backrefs" select="@backrefs"/>
<bibliomixed>
<xsl:attribute name="xml:id">
<xsl:value-of select="@id"/>
</xsl:attribute>
<xsl:call-template name="backrefs">
<xsl:with-param name="backrefs" select="$backrefs"/>
<xsl:with-param name="number" select="1"/>
</xsl:call-template>
<xsl:apply-templates select="paragraph" mode="biblio"/>
</bibliomixed>
</xsl:template>
<xsl:template name="backrefs">
<xsl:param name="backrefs"/>
<xsl:param name="number"/>
<xsl:param name="current_backref">
<xsl:choose>
<xsl:when test="contains(normalize-space($backrefs),' ')">
<xsl:value-of select="substring-before(normalize-space($backrefs),' ')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="normalize-space($backrefs)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:param>
<xsl:param name="backrefs_end">
<xsl:choose>
<xsl:when test="contains(normalize-space($backrefs),' ')">
<xsl:value-of select="substring-after(normalize-space($backrefs),' ')"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:param>
<xsl:if test="$number = 1">
<xsl:value-of select="'('"/>
</xsl:if>
<link>
<xsl:attribute name="linkend">
<xsl:value-of select="$current_backref"/>
</xsl:attribute>
<xsl:value-of select="$number"/>
</link>
<xsl:choose>
<xsl:when test="$backrefs_end!=''">
<xsl:value-of select="', '"/>
<xsl:call-template name="backrefs">
<xsl:with-param name="backrefs" select="$backrefs_end"/>
<xsl:with-param name="number" select="$number + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="') '"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="paragraph" mode="biblio">
<xsl:apply-templates/>
</xsl:template>
<!--
HYPERLINK & FOOTNOTES
-->
<xsl:template match="reference">
<xsl:choose>
<xsl:when test="@refuri">
<link>
<xsl:attribute name="xlink:href">
<xsl:value-of select="@refuri"/>
</xsl:attribute>
<xsl:apply-templates/>
</link>
</xsl:when>
<xsl:when test="@refid">
<link>
<xsl:attribute name="linkend">
<xsl:value-of select="@refid"/>
</xsl:attribute>
<xsl:apply-templates/>
</link>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template match="footnote"/>
<xsl:template match="footnote" mode="move">
<footnote>
<xsl:attribute name="xml:id">
<xsl:value-of select="@id"/>
</xsl:attribute>
<xsl:apply-templates/>
</footnote>
</xsl:template>
<xsl:template match="footnote/label"/>
<xsl:template match="footnote_reference">
<xsl:param name="footRefNumber"
select="count(preceding::footnote_reference[@refid=current()/@refid])"/>
<xsl:choose>
<xsl:when test="$footRefNumber = 0">
<xsl:apply-templates select="//footnote[@id=current()/@refid]" mode="move"/>
</xsl:when>
<xsl:otherwise>
<footnoteref>
<xsl:attribute name="xml:id">
<xsl:value-of select="@id"/>
</xsl:attribute>
<xsl:attribute name="linkend">
<xsl:value-of select="@refid"/>
</xsl:attribute>
</footnoteref>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!--
TABLES
-->
<xsl:template match="table">
<informaltable>
<xsl:apply-templates/>
</informaltable>
</xsl:template>
<xsl:template match="tgroup">
<tgroup>
<xsl:attribute name="cols">
<xsl:value-of select="@cols"/>
</xsl:attribute>
<xsl:apply-templates/>
</tgroup>
</xsl:template>
<xsl:template match="colspec">
<colspec>
<xsl:attribute name="colwidth">
<xsl:value-of select="@colwidth"/>
</xsl:attribute>
</colspec>
</xsl:template>
<xsl:template match="thead">
<thead>
<xsl:apply-templates/>
</thead>
</xsl:template>
<xsl:template match="tbody">
<tbody>
<xsl:apply-templates/>
</tbody>
</xsl:template>
<xsl:template match="row">
<row>
<xsl:apply-templates/>
</row>
</xsl:template>
<xsl:template match="entry">
<entry>
<xsl:if test="@morerows">
<xsl:attribute name="morerows">
<xsl:value-of select="@morerows"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@morecols">
<xsl:attribute name="morecols">
<xsl:value-of select="@morecols"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</entry>
</xsl:template>
<!--
FIGURES & IMAGES
-->
<xsl:template match="figure">
<figure>
<xsl:apply-templates select="caption"/>
<xsl:apply-templates select="image"/>
</figure>
</xsl:template>
<xsl:template match="image">
<mediaobject>
<imageobject>
<imagedata>
<xsl:if test="@uri">
<xsl:attribute name="fileref">
<xsl:value-of select="@uri"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@height">
<xsl:attribute name="height">
<xsl:value-of select="@height"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@width">
<xsl:attribute name="width">
<xsl:value-of select="@width"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@scale">
<xsl:attribute name="scale">
<xsl:value-of select="@scale"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@align='center'
or @align='left'
or @align='right'">
<xsl:attribute name="align">
<xsl:value-of select="@align"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@align='top'
or @align='middle'
or @align='bottom' ">
<xsl:attribute name="valign">
<xsl:value-of select="@align"/>
</xsl:attribute>
</xsl:if>
</imagedata>
</imageobject>
<xsl:if test="@alt">
<textobject>
<xsl:value-of select="@alt"/>
</textobject>
</xsl:if>
<xsl:if test="../legend">
<xsl:apply-templates select="../legend"/>
</xsl:if>
</mediaobject>
</xsl:template>
<xsl:template match="caption">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
<xsl:template match="legend">
<caption>
<xsl:apply-templates/>
</caption>
</xsl:template>
<!--
ADMONITIONS & NOTES
-->
<xsl:template match="note">
<note>
<xsl:apply-templates/>
</note>
</xsl:template>
<xsl:template match="important">
<important>
<xsl:apply-templates/>
</important>
</xsl:template>
<xsl:template match="caution|attention">
<caution>
<xsl:if test="name(.)!='caution'">
<xsl:attribute name="role">
<xsl:value-of select="name(.)"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</caution>
</xsl:template>
<xsl:template match="warning|danger|error">
<warning>
<xsl:if test="name(.)!='warning'">
<xsl:attribute name="role">
<xsl:value-of select="name(.)"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</warning>
</xsl:template>
<xsl:template match="tip|hint">
<tip>
<xsl:if test="name(.)!='tip'">
<xsl:attribute name="role">
<xsl:value-of select="name(.)"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</tip>
</xsl:template>
<!--
OTHER
-->
<xsl:template match="comment">
<xsl:comment>
<xsl:value-of select="."/>
</xsl:comment>
</xsl:template>
<xsl:template match="substitution_definition"/>
</xsl:stylesheet>

View File

@ -37,6 +37,7 @@ console_scripts =
openstack-generate-docbook = os_doc_tools.handle_pot:generatedocbook openstack-generate-docbook = os_doc_tools.handle_pot:generatedocbook
openstack-generate-pot = os_doc_tools.handle_pot:generatepot openstack-generate-pot = os_doc_tools.handle_pot:generatepot
openstack-jsoncheck = os_doc_tools.jsoncheck:main openstack-jsoncheck = os_doc_tools.jsoncheck:main
openstack-dn2osdbk = os_doc_tools.dn2osdbk:main
[build_sphinx] [build_sphinx]
source-dir = doc/source source-dir = doc/source