我需要帮助构建用于文本分隔的正则表达式。现在我有一些类似的文本
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"
如何构建正确的正则表达式?
它应该位于以下位置:
$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,查找和删除表,查找所有文本节点,并用它们的内容填充数组。您应该阅读更多关于PHPDOM的内容,以便根据您的需要对其进行微调。
去掉正则表达式开头和结尾的(.*)
。唯一一次需要"填充"这样的regex是在使用类似Java的matches()
方法时,该方法会自动在两端锚定匹配。
这里发生的情况是,第一个(.*)
最初吞噬了整个文档,然后后退到足以让下一部分(<table
等)匹配一个表元素的程度。然后,第二CCD_ 5消耗剩余的任何东西。这就解释了为什么preg_match_all()
只捕获一个表元素,以及为什么它总是最后一个。
你也可以去掉(?s)
。它并没有真正伤害任何东西,但它所做的只是打开single-line
模式,并且您已经在最后使用s
修饰符完成了这一操作。您可能想匹配一个空白字符(应该是's
),但这会阻止它匹配<table>
(即没有属性的表标记)。您应该使用'b
(单词边界):
preg_match_all( '~<table'b.*?/table>~si', $value[ 'TEXT' ], $matches );
但是要注意,这种方法只适用于极其简单的HTML。即使在完全有效的HTML中,也有很多事情可以击败它(嵌套的表标记是最明显的例子)。
最好的解决方案是这个代码:
$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' ] );
}
}
}