docbook: Factor out code to write valid DocBook IDs

Attributes in XML may contain alphanumeric characters, underscores,
colons and dots.  When DocBook is chunked, the dot is often used as a
path separator.  To generate a valid ID, we take the title of the
section, transform all non-alphanumeric characters to underscores and
then add a prefix separated with dots.  We also add the document name as
a prefix, in order to 'xinclude' eg. cmake.docbook and ctest.docbook in
the same document.  IDs are written in multiple places, so the code is
factored to a function.
This commit is contained in:
Daniel Pfeifer 2012-09-07 10:35:08 +02:00 committed by Brad King
parent cffa899a47
commit dbfe335099
2 changed files with 36 additions and 37 deletions

View File

@ -11,6 +11,8 @@
============================================================================*/ ============================================================================*/
#include "cmDocumentationFormatterDocbook.h" #include "cmDocumentationFormatterDocbook.h"
#include "cmDocumentationSection.h" #include "cmDocumentationSection.h"
#include <algorithm>
#include <ctype.h> // for isalnum
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// this function is a copy of the one in the HTML formatter // this function is a copy of the one in the HTML formatter
@ -107,21 +109,9 @@ void cmDocumentationFormatterDocbook
{ {
if(name) if(name)
{ {
std::string id = "section_"; os << "<sect1 id=\"";
id += name; this->PrintId(os, 0, name);
if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end()) os << "\">\n<title>" << name << "</title>\n";
{
this->EmittedLinkIds.insert(id);
os << "<sect1 id=\"section_" << name << "\">\n"
"<title>\n" << name << "</title>\n";
}
else
{
static unsigned int i=0;
i++;
os << "<sect1 id=\"section_" << name << i << "\">\n"
"<title>\n" << name << "</title>\n";
}
} }
std::string prefix = this->ComputeSectionLinkPrefix(name); std::string prefix = this->ComputeSectionLinkPrefix(name);
@ -138,28 +128,8 @@ void cmDocumentationFormatterDocbook
{ {
if(op->Name.size()) if(op->Name.size())
{ {
os << " <para id=\"" << prefix << "_"; os << " <para id=\"";
cmDocumentationPrintDocbookEscapes(os, op->Name.c_str()); this->PrintId(os, prefix.c_str(), op->Name);
// make sure that each id exists only once. Since it seems
// not easily possible to determine which link refers to which id,
// we have at least to make sure that the duplicated id's get a
// different name (by appending an increasing number), Alex
std::string id = prefix;
id += "_";
id += op->Name;
if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end())
{
this->EmittedLinkIds.insert(id);
}
else
{
static unsigned int i=0;
i++;
os << i;
}
// continue as normal...
os << "\"><sect2><title>"; os << "\"><sect2><title>";
cmDocumentationPrintDocbookEscapes(os, op->Name.c_str()); cmDocumentationPrintDocbookEscapes(os, op->Name.c_str());
os << "</title></sect2> "; os << "</title></sect2> ";
@ -213,6 +183,8 @@ void cmDocumentationFormatterDocbook::PrintHeader(const char* docname,
const char* appname, const char* appname,
std::ostream& os) std::ostream& os)
{ {
this->docname = docname;
// this one is used to ensure that we don't create multiple link targets // this one is used to ensure that we don't create multiple link targets
// with the same name. We can clear it here since we are at the // with the same name. We can clear it here since we are at the
// start of a document here. // start of a document here.
@ -235,3 +207,28 @@ void cmDocumentationFormatterDocbook::PrintFooter(std::ostream& os)
os << "</article>\n"; os << "</article>\n";
} }
//----------------------------------------------------------------------------
void cmDocumentationFormatterDocbook
::PrintId(std::ostream& os, const char* prefix, std::string id)
{
std::replace_if(id.begin(), id.end(), std::not1(std::ptr_fun(isalnum)), '_');
if(prefix)
{
id = std::string(prefix) + "." + id;
}
os << this->docname << '.' << id;
// make sure that each id exists only once. Since it seems
// not easily possible to determine which link refers to which id,
// we have at least to make sure that the duplicated id's get a
// different name (by appending an increasing number), Alex
if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end())
{
this->EmittedLinkIds.insert(id);
}
else
{
static unsigned int i=0;
os << i++;
}
}

View File

@ -35,7 +35,9 @@ public:
virtual void PrintPreformatted(std::ostream& os, const char* text); virtual void PrintPreformatted(std::ostream& os, const char* text);
virtual void PrintParagraph(std::ostream& os, const char* text); virtual void PrintParagraph(std::ostream& os, const char* text);
private: private:
void PrintId(std::ostream& os, const char* prefix, std::string id);
std::set<std::string> EmittedLinkIds; std::set<std::string> EmittedLinkIds;
std::string docname;
}; };
#endif #endif