是否可以通过 DXL 脚本实现?
恕我直言。我已经编写了一个 DXL 脚本来将 DOORS 模块导出到可以编译成 PDF 的 LaTeX 文件。您将在此答案的末尾找到它。随意调整它以适应您的需求。在运行它之前,您需要下载“ Smart Folder Browser ”的源代码,并将其存储在我的脚本之外,作为“smartFolderBrowser.inc”。Die extension inc 表示这是一个包含文件,而不是一个独立的 DXl 程序。
当然,每个想要使用这种方法的用户都需要一个已安装的 TeX 发行版,比如MiKTeX。DXL 脚本可以在导出后使用 DXL 内置功能启动 PDF 构建void system(string command)
。
使用您的自定义 DXL LaTeX 导出脚本,您必须完全控制生成的 PDF 的布局。但请注意 TeX 应用的布局规则。配置(强制)TeX 以呈现文档是一项非常具有挑战性的任务,因为它是使用 M$ Word 创建的。
// DOORS LaTeX Export
/**
Copyright (c) 2012-2013 Kai K.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
pragma encoding, "UTF-8"
#include "smartFolderBrowser.inc"
DBE dbeOutputFolder = null;
DBE dbeOptions = null;
bool withTitles = true
Buffer tempBuf = create;
void escapeSpecialLaTeXCharacters(Buffer& str)
{
Buffer temp = create;
int i = 0;
for(i = 0; i < length(str); ++i)
{
char c = str[i];
if( '\\' == c )
{
temp += "\\textbackslash{}";
}
else if( '{' == c )
{
temp += "\\"
temp += c
}
else if( '}' == c )
{
temp += "\\"
temp += c
}
else if( '_' == c )
{
temp += "\\"
temp += c
}
else if( '^' == c )
{
temp += "\\textasciicircum{}";
}
else if( '#' == c )
{
temp += "\\"
temp += c
}
else if( '&' == c )
{
temp += "\\"
temp += c
}
else if( '$' == c )
{
temp += "\\"
temp += c
}
else if( '%' == c )
{
temp += "\\"
temp += c
}
else if( '~' == c )
{
temp += "\\textasciitilde{}";
}
else
{
temp += c;
}
}
str = tempStringOf(temp);
delete temp;
}
string makeLabel(Buffer& str)
{
setempty(tempBuf);
int i = 0;
for(i = 0; i < length(str); ++i)
{
char c = str[i];
if( ' ' != c && '-' != c && '\n' != c && '\\' != c && '_' != c && '#' != c)
{
tempBuf += c;
}
}
return stringOf(tempBuf);
}
string makeCaption(Buffer& str)
{
setempty(tempBuf);
int i = 0;
for(i = 0; i < length(str); ++i)
{
char c = str[i];
if( '\n' != c && '\\' != c)
{
tempBuf += c;
}
}
escapeSpecialLaTeXCharacters(tempBuf);
return stringOf(tempBuf);
}
void rtf2latex(Buffer& buf)
{
Buffer txt = create;
Buffer temp = create;
RichTextParagraph rp = null;
bool envopened = false;
for rp in tempStringOf(buf) do {
if(rp.indentLevel > 0)
{
real hspace = realOf(rp.indentLevel)/20.0;
temp += "{\\hangindent" hspace "pt\\hangafter0"
}
if(rp.isBullet)
{
temp += "\\textbullet ";
}
RichText rt = null
for rt in rp do {
txt = rt.text;
escapeSpecialLaTeXCharacters(txt);
if (rt.italic)
{
temp += "\\textit{";
temp += txt;
temp += "}";
}
else if (rt.bold)
{
temp += "\\textbf{";
temp += txt;
temp += "}";
}
else if (rt.strikethru)
{
temp += "\\sout{";
temp += txt;
temp += "}";
}
else if (rt.subscript)
{
temp += "\\textsubscript{";
temp += txt;
temp += "}";
}
else if (rt.superscript)
{
temp += "\\textsuperscript{";
temp += txt;
temp += "}";
}
else if (rt.underline)
{
temp += "\\underline{";
temp += txt;
temp += "}";
}
else
{
temp += txt;
}
if (rt.newline && !rt.last)
{
temp += "\\par\n";
}
else if(rt.last)
{
temp += "\n";
}
}
if(rp.indentLevel > 0)
{
temp += "}"
}
}
buf = tempStringOf(temp);
delete temp;
delete txt;
}
void getObjectText(Object obj, Buffer& buf)
{
if(!null(obj))
{
buf = richTextFragment(richText(obj."Object Text"));
rtf2latex(buf);
}
else
{
buf = "null";
print("ERROR: obj null!: "dxlHere() "\n");
}
}
int nextCell(Stream& oss, int curCol, int numCols )
{
if( curCol == numCols )
{
oss << "\\\\\n\\hline\n"
}
else
{
oss << "\t&\t"
}
return( curCol % numCols + 1 )
}
void writePreamble(Stream& oss)
{
oss << "\\documentclass[a4paper]{book}\n";
oss << "%---- packages ----\n";
oss << "\\usepackage{ulem}\n";
oss << "\\usepackage{color}\n";
oss << "\\usepackage{graphicx}\n";
oss << "\\usepackage{supertabular}\n";
oss << "\\usepackage{hyperref}\n";
oss << "\\usepackage{makeidx}\n";
oss << "\\usepackage{xltxtra}\n";
oss << "\\makeindex\n";
oss << "%\n---- settings ----\n";
oss << "\\setcounter{secnumdepth}{6}\n";
oss << "\\setlength{\\parindent}{0}\n";
oss << "\\setlength{\\parskip}{2x}\n";
oss << "%\n---- customizations ----\n";
oss << "\\makeatletter\n";
oss << "\\def\\maxwidth{%\n";
oss << "\\ifdim\\Gin@nat@width>\\linewidth\n";
oss << "\\linewidth\n";
oss << "\\else\n";
oss << "\\Gin@nat@width\n";
oss << "\\fi\n";
oss << "}\n";
oss << "\\makeatother\n";
oss << "\n%---- document ----\n";
oss << "\\begin{document}\n";
oss << "\\tableofcontents\n";
oss << "\\listoffigures\n";
oss << "\\listoftables\n";
}
void writeTableHeader(Stream& oss, Object tableobj, int& numCols )
{
//print("Enter: writeTableHeader\n");
numCols = 0
int numRows = 0;
int tableWidth = 0;
Object cellobj = null;
Object rowobj = null;
// first count the columns and rows
for rowobj in table( tableobj ) do {
if( !isDeleted( rowobj ) )
{
if(numCols == 0)
{
for cellobj in rowobj do {
if( !isDeleted( cellobj ))
{
tableWidth += getCellWidth(cellobj);
numCols++;
}
}
}
numRows++;
}
}
// extract the header row
int colCount = numCols;
int col = 0;
Object headrow[colCount];
for rowobj in table( tableobj ) do {
if( !isDeleted( rowobj ) )
{
if(col == 0)
{
for cellobj in rowobj do {
if( !isDeleted( cellobj ))
{
headrow[col] = cellobj;
col++;
}
}
}
else
{
break;
}
}
}
// export the table head
oss << "\\begin{centering}\n";
Buffer buf = create;
oss << "\\tablefirsthead{";
for(col=0; col<colCount; ++col) {
getObjectText(headrow[col], buf);
oss << tempStringOf(buf);
if(col+1<colCount)
oss << "&";
}
oss << "\\\\}\n";
oss << "\\tablehead{";
for(col=0; col<colCount; ++col) {
getObjectText(headrow[col], buf);
oss << tempStringOf(buf);
if(col+1<colCount)
oss << "&";
}
oss << "\\\\}\n";
oss << "\\tabletail{\\hline}\n";
oss << "\\begin{supertabular}{|";
for(col=0; col<colCount; ++col) {
cellobj = headrow[col];
int w = getCellWidth(cellobj);
real rw = w;
real tw = tableWidth;
w = intOf(rw/tw*100.0);
rw = realOf(w)/100.0;
oss << "p{" rw "\\textwidth}|";
}
oss << "}\n\\hline\n"
delete buf;
//print("Leave: writeTableHeader\n");
}
void writeTableFooter(Stream& oss, Buffer& objtext)
{
oss << "\\\\\n\\hline\n"
oss << "\\end{supertabular}\n\\label{tab:";
oss << makeLabel( objtext );
oss << "}\n\\bottomcaption{"
oss << makeCaption( objtext );
oss << "}\n\\end{centering}\n"
}
void writeobjheading(Stream& oss, Buffer &objNum, Buffer &text, int level )
{
if(1 == level)
{
oss << "\\chapter{";
}
else if(2 == level)
{
oss << "\\section{";
}
else if(3 == level)
{
oss << "\\subsection{";
}
else if(4 == level)
{
oss << "\\subsubsection{";
}
else if(5 == level)
{
oss << "\\paragraph{";
}
else
{
oss << "\\subparagraph{";
}
oss << tempStringOf(text);
oss << "}\n\\label{sec:";
oss << makeLabel(text);
oss << makeLabel(objNum);
oss << "}\n";
}
void writeFigureHeadAndExport(Stream& oss, Object img, string outputDir)
{
Module mod = module(img);
string n = mod."Prefix"img."Absolute Number"".png";
string s = exportPicture(img, outputDir "\\" n, formatPNG);
oss << "\\begin{figure}[ht]\n";
oss << "\\centering\n";
oss << "\\includegraphics[width=\\textwidth]{"n"}\n";
}
void writeFigureFooter(Stream& oss, Buffer& objtext)
{
oss << "\\label{fig:";
oss << makeLabel( objtext );
oss << "}\n\\caption{"
oss << makeCaption( objtext );
oss << "}\n\\end{figure}\n";
}
void writeRequirement(Stream& oss, Module& doorsModule, Object obj, Buffer& puid, Buffer& objtext)
{
oss << "\\textbf{";
oss << tempStringOf( puid );
oss << "}\\\\\n" //"PUID style"
oss << "\\label{req:";
oss << makeLabel(puid)
oss << "}\n";
oss << "\\index{";
oss << tempStringOf( puid );
oss << "}\n";
oss << "\\color{blue}\n"
oss << tempStringOf( objtext )
oss << "\n"//"requirement style"
oss << "\\begin{tabbing}\n"
Column col = null;
Buffer var_name = create;
int c=0;
for col in doorsModule do {
var_name = title( col )
escapeSpecialLaTeXCharacters(var_name);
if( ! main( col ) && search( regexp "(P|p)(U|u)(I|i)(D|d)", var_name, 0 ) == false )
{
oss << "\\textbf{";
oss << var_name;
if(c == 0)
oss << "}: \\hspace{2.0cm} \\= "
else
oss << "}: \\> "
var_name = text( col, obj );
escapeSpecialLaTeXCharacters(var_name);
oss << var_name;
oss << "\\\\\n";// "attribute valueBuf" )
c++;
}
}
oss << "\\end{tabbing}\n"
oss << "\\color{black}\n"
delete var_name;
}
void timeString( int timeInSeconds, Buffer &t )
{
t = ""
int hours, minutes, seconds
hours = timeInSeconds / 3600
minutes = ( timeInSeconds - hours * 3600 ) / 60
seconds = ( timeInSeconds - hours * 3600 - minutes * 60 )
if( hours < 10 ) t = "0"
t += ( hours "")
t += ":"
if( minutes < 10 ) t += "0"
t += ( minutes "")
t += ":"
if( seconds < 10 ) t += "0"
t += ( seconds "")
}
void doExport(DB db)
{
int startTime = intOf( today )
int progressLimit = 0;
Object obj = null;
for obj in current Module do {
progressLimit++;
}
progressStart(db, "Exporting Module as LaTeX", "Object 0/"progressLimit"", progressLimit);
string outputDir = get(dbeOutputFolder);
string outputFileName = name(current Module);
string outputFileExt = ".tex";
string outputFilePath = outputDir "\\" outputFileName outputFileExt;
Stream mainFile = write(outputFilePath);
Stream oss = mainFile;
writePreamble(oss);
int progress = 1;
int curCol = 1;
int numCols = 0;
bool lastObjWasFigure = false;
bool lastObjWasTable = false;
Buffer objheading = create;
Buffer objtext = create;
Buffer objNum = create;
Buffer puid = create;
int lev = 0
int puidLevel = 0
Regexp excel = regexp "objclass Excel.Sheet"
Module doorsModule = current Module;
int subfileCount = 1;
for obj in current Module do {
if(progressCancelled())
{
if( confirm(db, "Do you really want to abort the export?") )
{
break;
}
}
progressMessage("Object "progress"/"progressLimit"");
getObjectText(obj, objtext)
// ------------------- Handle Tables ------------------------------------
if( cell( obj ))
{
if( !lastObjWasTable )
{
writeTableHeader(oss, obj, numCols);
curCol = 1;
lastObjWasTable = true;
}
else
{
curCol = nextCell(oss, curCol, numCols );
}
oss << tempStringOf( objtext ); // "Standard"
progressStep(progress);
progress++;
continue
}
// ------------------- After Table write Table Title -----------------
if( lastObjWasTable )
{
writeTableFooter(oss, objtext);
}
// ------------------- After Figure write Figure Title ---------------
if( lastObjWasFigure )
{
writeFigureFooter(oss, objtext)
}
objNum = number( obj )
objheading = obj."Object Heading"
escapeSpecialLaTeXCharacters(objheading)
// ------------------- Handle End of Requirement ------------------------
lev = level( obj )
if( lev <= puidLevel )
{
//oss << "End Requirement\n\n"
puidLevel = 0
}
if( withTitles && ( lastObjWasTable || lastObjWasFigure ))
{
lastObjWasTable = false
lastObjWasFigure = false
continue
}
// ------------------- Handle objheading with hierarchy --------------------
if( length( objheading ) > 0 )
{
writeobjheading(oss, objNum, objheading, lev )
}
if( length( objtext ) > 0 )
{
// remember, if Title has to be written after this object
if( containsOle( obj."Object Text"))
{
if( excel objtext ) {
lastObjWasTable = true
}
else
{
lastObjWasFigure = true;
writeFigureHeadAndExport(oss, obj, outputDir);
}
}
// ------------------- Handle Requirements objects Text -----------
puid = obj."IE PUID"
escapeSpecialLaTeXCharacters(puid)
if( length( puid ) > 0 )
{
puidLevel = lev
writeRequirement(oss, doorsModule, obj, puid, objtext);
}
// ------------------- No PUID means normal text Object -----------
else
{
oss << tempStringOf( objtext );
oss << "\n";// "Standard"
}
}
progressStep(progress);
progress++;
}
oss << "\\printindex\n"
oss << "\\end{document}\n";
close(oss);
progressStop();
// ---------------------- show the result ----------------------------------
int endTime = intOf( today ) - startTime
Buffer totalTime = create;
timeString( endTime, totalTime );
infoBox( "Export successfully finished after " totalTime "\nThe result is located in\n" outputFilePath);
delete objheading;
delete objtext;
delete objNum;
delete puid;
delete tempBuf;
}
DB db = create("LaTeX Export");
dbeOutputFolder = smartFolderBrowser(db, "Output Folder:", false);
ok(db, doExport);
show(db);