-2

我需要帮助构建用于文本分隔的正则表达式。现在我有一些文字

text text text
text text text
<div> text text text </div>
<table class="table1">
<tr>
<td>
</td>
</tr>
</table>
text text text
text text text
text text text
<table class="table2">
<tr>
<td>
</td>
</tr>
</table>
text text text
text text text
text text text

我需要创建一个将文本和表格分开的正则表达式。现在我有正则表达式

preg_match_all( "/(.*)(<table(?s).*?\/table>)(.*)/si", $value[ 'TEXT' ], $matches );

这个表达式适用于像这样的文本

text text text
text text text
<div> text text text </div>
<table class="table1">
<tr>
<td>
</td>
</tr>
</table>

它与

text text text
text text text
<div> text text text </div>

    <table class="table1">
    <tr>
    <td>
    </td>
    </tr>
    </table>

但是对于文字

text text text
text text text
<div> text text text </div>
<table class="table1">
<tr>
<td>
</td>
</tr>
</table>
text text text
text text text
text text text
<table class="table2">
<tr>
<td>
</td>
</tr>
</table>
text text text
text text text
text text text

我的正则表达式不起作用。它是返回数组

[0] =>"text text text
    text text text
    <div> text text text </div>
    <table class="table1">
    <tr>
    <td>
    </td>
    </tr>
    </table>
    text text text
    text text text
    text text text",
[1]=>"<table class="table2">
    <tr>
    <td>
    </td>
    </tr>
    </table>",
[2]=>"text text text
    text text text
    text text text"

如何构建正确的正则表达式?

4

3 回答 3

1

它应该在这附近的某个地方:

$doc = new DOMDocument;
$doc->loadHTML('html string');

$tables = $doc->getElementsByTagName('table');
foreach($tables as $table){
    $parent = $table->parentNode;
    $parent->removeChild($table);
}

$doc->normalizeDocument();

$text = array();
$xpath = new DOMXPath($doc);
$textnodes = $xpath->evaluate('//text()');
foreach($textnodes as $textnode){
    $text[] = $textnode->wholeText;
}
print_r($text)

此代码加载您的 html、查找和删除表、查找所有文本节点并用它们的内容填充数组。您应该阅读有关PHP DOM的更多信息,以根据您的需要对其进行微调。

于 2012-09-10T08:40:35.117 回答
0

摆脱(.*)正则表达式开头和结尾的 。唯一一次你必须“填充”这样的正则表达式是当你使用类似 Java 的matches()方法时,它会自动在两端锚定匹配。

这里发生的情况是,第一个(.*)最初吞噬了整个文档,然后后退到足以让下一部分(<table等)匹配一个表格元素。然后第二个(.*)消耗掉剩下的东西。这就解释了为什么preg_match_all()只捕获一个表格元素,以及为什么它总是最后一个。

你也可以摆脱(?s)。它并没有真正伤害任何东西,但它所做的只是打开single-line模式,并且您已经s在最后使用修饰符完成了该操作。您可能打算匹配一个空白字符(应该是\s),但这会阻止它匹配<table>(即没有属性的表标签)。您应该改用\b(单词边界):

preg_match_all( '~<table\b.*?/table>~si', $value[ 'TEXT' ], $matches );

但请注意,这种方法仅适用于极其简单的 HTML。即使在完全有效的 HTML 中,也有很多很多东西可以打败它(嵌套表格标签是最明显的例子)。

于 2012-09-10T09:45:13.937 回答
0

最好的解决方案是这段代码:

$test = preg_replace( "/<table(?s).*?\/table>/si", '<BREAKHERE>', $value[ 'TEXT' ] );

            $texts = explode( '<BREAKHERE>', $test );

            foreach ( $texts as $keyTEXT => $valueTEXT )
            {
                $TmpVal = str_replace( "\r", "", $valueTEXT );
                $TmpVal = str_replace( "\n", "", $TmpVal );
                $TmpVal = str_replace( "\r\n", "", $TmpVal );
                if ( trim( $TmpVal ) != '' )
                {
                    preg_match_all( "/\w/", $TmpVal, $mtchs );

                    if ( count( $mtchs[ 0 ] ) > 0 )
                    {
                        $value[ 'TEXT' ] = str_replace( $valueTEXT, ' <div class="panel-container">' . $valueTEXT . '</div>', $value[ 'TEXT' ] );
                    }
                }
            }
于 2012-09-10T12:14:57.657 回答