我需要帮助构建用于文本分隔的正则表达式。 现在我有一些像
这样的文字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"
如何构建正确的正则表达式?
答案 0 :(得分: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的更多信息,以便根据您的需要进行微调。
答案 1 :(得分: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中,也有很多东西可以打败它(嵌套表标签是最明显的例子)。
答案 2 :(得分: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' ] );
}
}
}