Search Lists which are in a table cell only

Any questions involving matching text strings to patterns - the pattern is called a "regular expression."

Moderator: General Moderators

Post Reply
radiks
Forum Newbie
Posts: 9
Joined: Thu Aug 22, 2013 4:12 am

Search Lists which are in a table cell only

Post by radiks »

Hi All,

I have the following problem. I want to insert in a table only these lists which are in a table cell. These which are not in a table let's keep it that way
Here is my code:
$replaceList = '$1$2<table class="listTbl"><tr><td>$3</td></tr></table>$4$5';
$html = preg_replace('/(<td>){1}(.*?)(<ul>[\s\S]*?<\/ul>)(.*?)(<\/td>){1}/smi', $replaceList, $html);

If there is following:
<table>
<tr>
<td>Test</td>
</tr>
<tr>
<td>
Text here
<ul>
<li>Test1</li>
<li>Test2</li>
</ul>
Text
</td>
</tr>
To become:
<table>
<tr>
<td>Test</td>
</tr>
<tr>
<td>
Text here
<table class="listTbl"><tr><td>
<ul>
<li>Test1</li>
<li>Test2</li>
</ul>
</td></tr></table>
Text
</td>
</tr>
Thanks!
Last edited by radiks on Tue Sep 24, 2013 9:03 am, edited 1 time in total.
radiks
Forum Newbie
Posts: 9
Joined: Thu Aug 22, 2013 4:12 am

Re: Search Lists which are in a table cell only

Post by radiks »

I forgot to mention that my code works, but where I have lists between 2 tables insert and them in the table. May be because I have (.*?)
How could I do to search only those lists that are in a table?

Thanks!
User avatar
ragax
Forum Commoner
Posts: 85
Joined: Thu Dec 15, 2011 1:40 pm
Location: Nelson, NZ

Re: Search Lists which are in a table cell only

Post by ragax »

I think you're going to need preg_replace_callback.
You can then (break)(your)(match)(into)(capture)(chunk) and reassemble everything however you want.

The easiest example of this is actually not on the preg_replace_callback page but on the anonymous function page.
radiks
Forum Newbie
Posts: 9
Joined: Thu Aug 22, 2013 4:12 am

Re: Search Lists which are in a table cell only

Post by radiks »

Thanks for the answer ragax!

I have a problem with the pattern. No matter which function use.
I want to find all lists that are in а table. But those who are outside the table do not care. As and my pattern includes in the matches and lists that are out of table, but they are between 2 tables because in it there is (.*?). i.e. looking for anything between <td> and </td>.
User avatar
ragax
Forum Commoner
Posts: 85
Joined: Thu Dec 15, 2011 1:40 pm
Location: Nelson, NZ

Re: Search Lists which are in a table cell only

Post by ragax »

Hi radiks,
To do this in regex, you need to use regex lookahead and lookbehind.

To give you an example, this pattern will match from an opening <td> to the next <li> that occurs before the closing </td>.
After that, you can start adding your capture groups etc.
(?s)<td>(?!.*?</td>.*?<li>).*?<li>
It says "match a <td>, then, { if at this point we cannot match stuff followed by a closing </td>, more stuff and a <li> }, match stuff then the <li>.

That should give you a place to start.

:)
radiks
Forum Newbie
Posts: 9
Joined: Thu Aug 22, 2013 4:12 am

Re: Search Lists which are in a table cell only

Post by radiks »

Hi ragax,

Thanks for your answer! :)
Almost happened but when I have a table without lists in it and after the table list that is not in a table then and this list enters in matches. Why? Where I'm wrong?

Here is my code:

Code: Select all

$html = preg_replace_callback('/(<td>)+(?!<td>.*?<\/table>.*?<ul>).*?(<ul>.*?<\/ul>)+.*?(<\/td>)+/smi', 'replaceCallbackFn', $html);
function replaceCallbackFn($matches)
{    
    if(is_array($matches) && !empty($matches))
    {
        return preg_replace('/(<td>)(.*?)(<ul>.*?<\/ul>)(.*?)(<\/td>)/smi','$1$2<table class="listTbl" style="border:1px solid red; color:green;"><tr><td>$3</td></tr></table>$4$5',$matches[0]);        
    }   
    
}  
radiks
Forum Newbie
Posts: 9
Joined: Thu Aug 22, 2013 4:12 am

Re: Search Lists which are in a table cell only

Post by radiks »

I feel powerless!

I found another case where my code does not work.
Here are two cases that I noticed:
Case 1:
<table width="100%" border=1>
<tr>
<td>
Text here!
</td>
</tr>
</table>
<ul>
<li>List Text 1</li>
<li>List Text 2</li>
</ul>
Case 2:
<table>
<tr>
<td>
<table>
<tr>
<td>
<ul><li>Test1</li><li>Test2</li></ul>
</td>
</tr>
</table>
<ul>
<li>List Text 1</li>
<li>List Text 2</li>
</ul>
</td>
</tr>
</table>
User avatar
ragax
Forum Commoner
Posts: 85
Joined: Thu Dec 15, 2011 1:40 pm
Location: Nelson, NZ

Re: Search Lists which are in a table cell only

Post by ragax »

Hi radiks,

I don't have time to look in detail today, but at first glance it looks to me that you may not be using preg_replace_callback properly. It looks like the function you are calling uses a preg_match. But the idea for the function you call is that you pass it the array of matches, then that it returns something with it: for instance return "some prefix".$matches[1]."some suffix";
Please have a look at Example #1 on this page, and particularly at what the callback function does (just a strtoupper), the syntax might be a lot simpler than you are thinking.
http://www.php.net/manual/en/functions.anonymous.php

That being said I did not read your code in detail and maybe there is a reason for a preg_match in the callback function, but that would be rare.
User avatar
ragax
Forum Commoner
Posts: 85
Joined: Thu Dec 15, 2011 1:40 pm
Location: Nelson, NZ

Re: Search Lists which are in a table cell only

Post by ragax »

Hi again. Thought I'd take a quick close look. This code addresses your original question (please run it). Simple replace so no need for a callback.

Code: Select all

$string = '<table>
    <tr>
    <td>Test</td>
    </tr>
    <tr>
    <td>
    Text here
    <ul>
    <li>Test1</li>
    <li>Test2</li>
    </ul>
    Text
    </td>
    </tr>
';
$regex = '~(?s)<td>(?!.*?</td>.*?<ul>).*?\K<ul>.*?</ul>~';
$replace = '<table class="listTbl"><tr><td>\0</td></tr></table>';
$newstring = preg_replace($regex,$replace,$string);
echo htmlentities($newstring).'<br />';
Does that take care of your problem?
Post Reply