问题在于:我有一个数据库,里面装满了用XHTML标记的文章。我们的应用程序使用Prince XML生成PDF。其中的一个神器是脚注以内联方式标记,使用以下模式:
<p>Some paragraph text<span class="fnt">This is the text of a footnote</span>.</p>
Prince使用数字脚注标记替换每个span.fnt
,并将所附文本作为脚注呈现在页面底部。
我们希望以电子书格式呈现相同的内容,而XHTML是一个很好的起点,但内联脚注非常糟糕。我想要做的是将脚注转换为我的电子书构建脚本中的尾注。
这就是我的想法:
$endnotes
的空数组来存储尾注文本。$endnote_no
设置为零。该变量将保存当前的尾注编号,以内联方式显示为尾注标记,并用于将尾注标记与特定尾注链接。preg_replace
或preg_replace_callback
查找<span class="fnt">(.*?)</span>
的每个实例。$endnote_no
,并将内联span
替换为'<sup><a href="#endnote_
'。 $ endnote_no。 '“&GT;' 。$ endnote_no。''`$endnotes
数组,以便我可以在文档末尾使用它。$endnotes
数组,将尾注作为XHTML中的有序列表吐出。这个过程有点超出了我的PHP理解范围,当我尝试将其转换为代码时,我迷失了方向。这是我到目前为止所做的,我主要根据我在PHP文档中找到的代码示例拼凑在一起:
$endnotes = array();
$endnote_no = 0;
class Endnoter {
public function replace($subject) {
$this->endnote_no = 0;
return preg_replace_callback('`<span class="fnt">(.*?)</span>`', array($this, '_callback'), $subject);
}
public function _callback($matches) {
array_push($endnotes, $1);
return '<sup><a href="#endnote_' . $this->endnote_no++ . '">' . $this->endnote_no . '</a></sup>';
}
}
...
$replacer = new Endnoter();
$replacer->replace($body);
echo '<pre>';
print_r($endnotes); // Just checking to see if the $endnotes are there.
echo '</pre>';
任何指导都会有所帮助,特别是如果有更简单的方法可以实现这一目标。
答案 0 :(得分:2)
首先,你最好使用正则表达式进行HTML操作而不是;看这里: How do you parse and process HTML/XML in PHP?
但是,如果您真的想要走这条路,那么您的代码就会出现一些问题:
return '<sup><a href="#endnote_' . $this->endnote_no++ . '">' . $this->endnote_no . '</a></sup>';
如果endnote_no为1,例如这将产生
'<sup><a href="#endnote_1">2</a></sup>';
如果这两个值都应该相同,那么首先要增加endnote_no:
return '<sup><a href="#endnote_' . ++$this->endnote_no . '">' . $this->endnote_no . '</a></sup>';
请注意调用前面的++而不是之后的。
array_push($endnotes, $1);
$1
不是定义的值。您正在寻找传入回调的数组,因此您需要$matches[1]
print_r($endnotes);
$endnotes
未在类外定义,因此您要么需要getter函数来检索$endnotes
(通常 ),要么在类中公开变量。有了吸气剂:
class Endnotes {
private $endnotes = array();
//replace any references to $endnotes in your class with $this->endnotes and add a function:
public function getEndnotes() {
return $this->endnotes;
}
}
//and then outside
print_r($replacer->getEndnotes());
preg_replace_callback
未通过引用传递,因此您实际上并未修改原始字符串。 $replacer->replace($body);
应为$body = $replacer->replace($body);
,除非您希望通过引用将正文传递到replace()
函数并在其中更新其值。
答案 1 :(得分:2)
不知道更简单的方法,但你已经到了一半。这似乎有效。
我刚刚清理了一下,移动了类中的变量并添加了一个输出方法来获取脚注列表。
class Endnoter
{
private $number_of_notes = 0;
private $footnote_texts = array();
public function replace($input) {
return preg_replace_callback('#<span class="fnt">(.*)</span>#i', array($this, 'replace_callback'), $input);
}
protected function replace_callback($matches) {
// the text sits in the matches array
// see http://php.net/manual/en/function.preg-replace-callback.php
$this->footnote_texts[] = $matches[1];
return '<sup><a href="#endnote_'.(++$this->number_of_notes).'">'.$this->number_of_notes.'</a></sup>';
}
public function getEndnotes() {
$out = array();
$out[] = '<ol>';
foreach($this->footnote_texts as $text) {
$out[] = '<li>'.$text.'</li>';
}
$out[] = '</ol>';
return implode("\n", $out);
}
}