【发布时间】:2012-01-18 16:58:00
【问题描述】:
我想创建一个 PHP 脚本,将 XML 格式化为电视/电影剧本,事实证明这比预期的要困难一些。我已经创建了一些代码,但是,在某些特定的地方我会卡住。
一点背景
在剧本中存在多个标签,如角色、对话、场景标题、过渡等。它们具有不同的宽度和左右边距,确定页面上的位置。
有两个主要领域受到关注,即我无法弄清楚:
- 父/子 XML 标签,不能分开。
- 如果子标签很长并且必须继续到另一个页面,则必须创建后续标签以显示它仍然是父标签。例如,如果显示一个字符标签,并且该标签的对话框(通过宽度、字符长度和行高)计算(通过宽度、字符长度和行高)以继续到下一页,那么父标签“字符”必须再次显示在下一页的顶部。
- 这样的父/孤标签包括:
- "sceneheadng" -> 任何标签。
- “字符”-> 对话框或括号
- “括号”-> 对话框
然而,理想情况下,父/子标签应该存储在这样的地方,这样可以在没有大量代码的情况下添加更多。
经过多次 FPDF 配置和尝试,这是我目前所拥有的:
// Parse the XML string which has been requested from the database.
$xml = new SimpleXmlIterator($file, null);
$namespaces = $xml->getNamespaces(true);
/*
* An external function which converts the XML into an ORDERED array.
* This returns all the attributes of the xml and the following:
* "@type" Refers to the type, i.e. character/dialog etc,
* "@content" What was actually within the tags of the XML.
*/
$source = $parseXML($xml, $namespaces);
$saved = array ();
// For every line of the XML.
foreach ($source as $index => $line) {
/*
* We are going to save the current line of the XML so that we
* can check the size of the saved cells against the size of the
* page. If there is not enough space for specific tags which are
* required such as character and dialog, then we create a new page.
*
*/
$saved[] = $line;
$forward = false;
/*
* Here is where I get somewhat confused - I have attempted to create
* a mechanism that determines the "@types" which are needed as parents
* and children of one another.
*
* The $forward variable refers to the possibilty of writing the tag to
* the PDF. If the parent/orphan is possible or there are non, then it
* should be able to write.
*/
if ($forward) {
$width = 0;
foreach ($saved as $index => $value) {
/*
* Everything is measured in inches, therefore, I have created a
* point() function which turns inches into mm so that FPDF understands
* everything.
*
* The $format variable is an array which has margins, either top,
* left or right. We use this to position the Cell of a specific @type
* so that it appears in the correct format for a TV/Film script.
*
* The width variable is deduced via finding the full width of the page,
* then subtracting the subsequent left and right margin of the said
* @type.
*/
$width = (point ($setting["width"])
- (point ($format[$value["@type"]]["margin-left"])
+ point ($format[$value["@type"]]["margin-right"])));
/*
* The $pdf variable is that of the FPDF Class.
*/
$pdf->SetLeftMargin (point($format[$value["@type"]]["margin-left"]));
$pdf->SetRightMargin (point($format[$value["@type"]]["margin-right"]));
// Formatting purposes.
$pdf->Ln (0);
$pdf->MultiCell (
$width,
point ($setting["line-height"]), //Line height? Still needs fixing.
$value["@content"], // Physical text
1); // A temporary border to see what's going on.
}
// Reset the $saved, after no more parent/children?
$saved = array ();
}
}
另外,我写了一个函数来计算组合“$saved”行的高度:
function calculate_page_breaks ($saved_lines, $act_upon = true) {
$num_lines = 0;
foreach ($saved_lines as $value) {
$column_width = (point ($setting["width"])
- (point ($format[$type][$value["@type"]]["margin-left"])
+ point ($format[$type][$value["@type"]]["margin-right"])));
$num_lines += ceil($pdf->GetStringWidth($value["@content"]) / ($column_width - 1));
}
$cell_height = 5 + 1; // have cells at a height of five so set to six for a padding
$height_of_cell = ceil($num_lines * $cell_height);
$space_left = point($setting["height"]) - $pdf->GetY();
$space_left -= point($format[$type]["margin-bottom"]);
// test if height of cell is greater than space left
if ($height_of_cell >= $space_left) {
// If this is not just a check, then we can physically "break" the page.
if ($act_upon) {
$pdf->Ln ();
$pdf->AddPage (); // page break
$pdf->SetTopMargin ($point($format[$type]["margin-top"]));
$pdf->SetLeftMargin ($point($format[$type]["margin-left"]));
$pdf->SetRightMargin ($point($format[$type]["margin-right"]));
$pdf->MultiCell (100,5,'','B',2); // this creates a blank row for formatting reasons
}
return false;
} else {
return true;
}
}
编辑
我发现 LaTeX 提供了一个剧本类(http://www.tug.org/texlive/Contents/live/texmf-dist/doc/latex/screenplay/screenplay.pdf),但是,我已经搜索过了并广泛寻找基于PHP的工具将LaTeX转换为PDF,但没有成功。我知道 LaTeX 在服务器端运行,但是我仍然需要基于 PHP 的命令进程才能使用 LaTeX 生成所述 PDF 文件。
此外,在服务器上安装二进制文件、库或工具是不允许的。我可以使用的工具是 PHP 及其内置的功能。任何可以将 LaTex 转换为 PDF 的类或 PHP 工具都非常有用。
【问题讨论】:
-
@Blender:不,但这对页边距/单元格格式/分页符等有什么帮助?
-
因为这就是 Latex 的用途 ;) 它用于排版杂志、书籍、教科书、研究论文等。它生成 PDF 文件。
-
甚至还有一个完整的
Screenplay类你可以使用:tug.org/texlive/Contents/live/texmf-dist/doc/latex/screenplay/… -
@Blender 如何开始为 Latex 编写 PHP 解析器,然后再编写为 PDF?
-
Latex 由 Tex 解析,而不是 PHP。您需要在 PHP 中创建一个
text -> latex脚本,然后在后台运行latex以生成 PDF。