在php中使用正则表达式在一行中添加一个单元格

发布于 2024-08-10 12:31:58 字数 1690 浏览 2 评论 0原文

像往常一样,我在编写好的正则表达式时遇到了困难。

我正在尝试为 Joomla 制作一个插件,以向文章标题右侧核心生成的可选打印、电子邮件和 PDF 按钮添加一个按钮。如果我成功了,我将在 GPL 下分发它。我发现的示例似乎都不起作用,我想创建一个仅 php 的解决方案。

这个想法是使用 Joomla 输出的独特模式作为一个或多个正则表达式的文章标题和按钮。一个正则表达式可以通过查找具有类“contentpaneopen”的表(其中一个页面中有多个)并包含具有类“contentheading”的单元格来找到正确的表。第二个正则表达式可以检查该表中是否存在具有“buttonheading”类的单元格。这些单元格的数量可以从零到三个,但如果第一个正则表达式返回多个匹配项,我可以使用此检查。有了这个,我想用同一个表替换该表,但有一个额外的单元格包含我想要添加的按钮。我可以通过去掉最后一行和表格结束标签并插入按钮单元格,然后再次添加这些结束标签来做到这一点。

正常的 Joomla 输出如下所示:

<table class="contentpaneopen">
    <tbody>
        <tr>
            <td width="100%" class="contentheading">
                <a class="contentpagetitle" href="url">Title Here</a>
            </td>
            <td width="100%" align="right" class="buttonheading">
                <a rel="nofollow" onclick="etc" title="PDF" href="url"><img alt="PDF" src="/templates/neutral/images/pdf_button.png"/></a>
            </td>
            <td width="100%" align="right" class="buttonheading">
                <a rel="nofollow" onclick="etc" title="Print" href="url"><img alt="Print" src="/templates/neutral/images/printButton.png" ></a>
            </td>
        </tr>
    </tbody>
</table>

代码大致如下:

$subject = $article;
$pattern1 = '[regex1]'; //<table class="contentpaneopen">etc</table>
preg_match($pattern, $subject, $match);
$pattern2 = '[regex2]'; //</tr></tbody></table>
$replacement = [mybutton];
echo preg_replace($pattern2, $replacement, $match);

如果没有好的正则表达式,则执行其余代码就没有什么意义,所以我希望有人可以提供帮助!

As usual I have trouble writing a good regex.

I am trying to make a plugin for Joomla to add a button to the optional print, email and PDF buttons produced by the core on the right of article titles. If I succeed I will distribute it under the GPL. None of the examples I found seem to work and I would like to create a php-only solution.

The idea is to use the unique pattern of the Joomla output for article titles and buttons for one or more regex. One regex would find the right table by looking for a table with class "contentpaneopen" (of which there are several in a page) and containing a cell with class "contentheading". A second regex could check if in that table there is a cell with class "buttonheading". The number of these cells could be from zero to three but I could use this check if the first regex returns more than one match. With this, I would like to replace the table by the same table but with an extra cell holding the button I want to add. I could do that by taking off the last row and table closing tags and inserting my button cell before adding those closing tags again.

The normal Joomla output looks like this:

<table class="contentpaneopen">
    <tbody>
        <tr>
            <td width="100%" class="contentheading">
                <a class="contentpagetitle" href="url">Title Here</a>
            </td>
            <td width="100%" align="right" class="buttonheading">
                <a rel="nofollow" onclick="etc" title="PDF" href="url"><img alt="PDF" src="/templates/neutral/images/pdf_button.png"/></a>
            </td>
            <td width="100%" align="right" class="buttonheading">
                <a rel="nofollow" onclick="etc" title="Print" href="url"><img alt="Print" src="/templates/neutral/images/printButton.png" ></a>
            </td>
        </tr>
    </tbody>
</table>

The code would very roughly be something like this:

$subject = $article;
$pattern1 = '[regex1]'; //<table class="contentpaneopen">etc</table>
preg_match($pattern, $subject, $match);
$pattern2 = '[regex2]'; //</tr></tbody></table>
$replacement = [mybutton];
echo preg_replace($pattern2, $replacement, $match);

Without a good regex there is little point doing the rest of the code, so I hope someone can help with that!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

枯寂 2024-08-17 12:31:58

这是 SO 上的一个常见问题,答案总是相同的:正则表达式对于解析或处理 HTML 或 XML 来说是一个糟糕的选择。有很多方法可以破坏它们。 PHP 至少带有三个内置的 HTML 解析器,它们会更加健壮。

看看使用 PHP 和 DOM 解析 HTML 并使用类似:

$html = new DomDocument;
$html->loadHTML($source); 
$html->preserveWhiteSpace = false; 
$tables = $html->getElementsByTagName('table'); 
foreach ($tables as $table) {
  if ($table->getAttribute('class') == 'contentpaneopen') {
    // replace it with something else
  }
}

This is a common question on SO and the answer is always the same: regular expressions are a poor choice for parsing or processing HTML or XML. There are many ways they can break down. PHP comes with at least three built-in HTML parsers that will be far more robust.

Take a look at Parse HTML With PHP And DOM and use something like:

$html = new DomDocument;
$html->loadHTML($source); 
$html->preserveWhiteSpace = false; 
$tables = $html->getElementsByTagName('table'); 
foreach ($tables as $table) {
  if ($table->getAttribute('class') == 'contentpaneopen') {
    // replace it with something else
  }
}
少女净妖师 2024-08-17 12:31:58

您是否需要为此使用正则表达式? DOM 解析会更加简单。

Is there a reason that you need to use regex for this? DOM parsing would be much more straightforward.

淡淡的优雅 2024-08-17 12:31:58

由于每次加载页面时都会调用您提供的场景中的插件,因此正则表达式方法比 dom 调用更快,这就是很多人使用这种方法的原因。在 Joomla 文档中,您也可以看到为什么在提供的场景中使用正则表达式比尝试使用dom 方法。

您的解决方案的问题在于它与 Joomla 的默认模板相关。我不记得它是否在所有模板中使用相同的 class="contentheading" 结构。如果您计划使用 GPL 这样的扩展,您应该小心这一点。

在我看来,您想要做的事情是模板覆盖,详细说明< a href="http://www.scribd.com/doc/2300107/Joomla-v-1-5-Getting-Started-with-Template-Overrides" rel="nofollow noreferrer">此处。是一个更简单的解决方案。例如,创建文章标题的 php:

<div class="componentheading<?php echo $this->params->get('pageclass_sfx')?>">
    <h2><?php echo $this->escape($this->params->get('page_title')); ?></h2>
</div>

您只需覆盖 com_content 文章模板,并在 >get('page_title') 调用后回显 pdf 按钮的 html。如果您不想回显 html,您可以创建一个模块或组件,将其导入模板中,然后在 >get('page_title') 后调用组件中的方法显示 html。

该组件可以有各种复选框“显示 pdf(是/否)”和其他有趣的操作。

Since a plugin in the scenario you provided is called everytime you load a page, a regex approach is faster than a dom call, that's why a lot of people use this approach. In Joomla's documentation, you can see too why a regex in the provided scenario is better than trying to use a dom approach.

The problem with your solution is that it's tied with Joomla's default template. I don't remember if it uses the same class="contentheading" structure in all templates. If you plan to GPL such an extension, you should be careful about that.

What you're trying to do seems to me as a template override, explained in more details here. Is a much more simpler solution. For example, the php that creates your article title's:

<div class="componentheading<?php echo $this->params->get('pageclass_sfx')?>">
    <h2><?php echo $this->escape($this->params->get('page_title')); ?></h2>
</div>

You just need to override the com_content article template, and echo the html for the pdf buttons after the >get('page_title') call. If you don't want to echo the html, you can create a module or a component, import it in the template and after the >get('page_title') you call the methods in your component that show the html.

This component could have various checkboxes "show pdf (yes/no)" and other interesting actions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文