Link to home
Start Free TrialLog in
Avatar of metalaureate
metalaureateFlag for United States of America

asked on

Finding the parent DIV given an insertion point, in PHP

How do I find the PARENT div in free-form XHTML string, given any insertion point, such as the following

<DIV> <-- this is the DIV I want0>
    <DIV>Not interested in this one</DIV>
    <DIV> Not this one either</DIV>
    <P>Here's my insertion point - I got to start here and work out who my parent DIV is</P>
     <DIV>Not this one either</DIV>
</DIV>

I've been trying to use http://simplehtmldom.sourceforge.net/ but I can't figure out how to use it for this particular operation.

I then tried direct string manipulation, but that was a mess.
Avatar of level9wizard
level9wizard
Flag of Canada image

I don't know if its possible, but If you could apply an id or class to that div, it might become a much easier undertaking whichever road you take. You can then use regex to traverse based on that unique id/class string.
Avatar of metalaureate

ASKER

Regrettably, all I am given is the insertion point, the rest is an infinite set of varying code.
Avatar of Adoryc666
Adoryc666

If you are using javascript you can use the method.parentNode on the element.
[metalaureate]>>Regrettably, all I am given is the insertion point, the rest is an infinite set of varying code.

Ah, that's too bad. I think your likely going to need some regex here regardless - so you might want to see if you can get this question tagged in there as well.
ASKER CERTIFIED SOLUTION
Avatar of hielo
hielo
Flag of Wallis and Futuna image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi hielo, my starting point is just an str_pos... but suppose I crawl back to the nearest element (p or div), I then give that a unique ID, then I transform that to a DOM object using simplehtmldom, and THEN get the parent.

Problem then is, what if the nearest element is already the parent DIV? How do I detect that? Otherwise, in this case, I am going to get the grandparent and not know it.
try:
echo $e->parent()->tag;

should give you the name of the tag for the whatever parent() refers to.
To clarify, how to I detect this situation

<DIV>
My insertion point is here.
</DIV>

Maybe, the rule is: go back to nearest element and get its parent, unless you don't encounter any close tag </ on the way back, in which case assume that's the parent.
>>My insertion point is here.
How are you doing this?
Ok, my function gets a string that contains a custom tag, e.g.

<div>
<div></div>
<div></div>
~~#
<div></div>
</div>

What I know is the location of ~~#. I then have to find its parent DIV - none of the elements have meaningful Ids, but there could be any amount of other code surrounding it.

If I crawl back to the nearest element, in this example, that's a div whose parent is INDEED what I want.

However, in this example:

<div
hdfhjsdjsfhsdfs
~~#
</div>

If I crawl back and get that parent's div, I will get the grandparent.

So, in order to detect whether or not the node I crawl back to is already the parent, I thought I could detect the presence of any closing tags "/>", as the absence of a closing tag would indicate that there were no elements between my insertion point and my parent div,

Does that seem right?

Thanks for your help!
I think the "p" block below is basically what you are after.
<?php
include_once('simple_html_dom.php');
$str=<<<HTML
<html><body>
<div id='x'>
<div></div>
<div></div>
<p>~~#</p>
<div></div>
</div>
</body></html>
HTML;

$html=str_get_html($str);
$divSet=$html->find('div');

foreach($divSet as $i=>$div)
{
	if( preg_match('/~~#/',$div->plaintext) )
	{
		echo $div->getAttribute('id');
		echo $div->tag;
	}
}

$pSet=$html->find('p');
foreach($pSet as $i=>$p)
{
	if( preg_match('/~~#/',$p->plaintext) )
	{
		echo $p->tag;
		echo "parent:" . $p->parent()->tag;
	}
}
?>

Open in new window

Let me try that, I'll be back later. Thanks for all your help!
OK
This put me on to the solution. Thank you! All I needed to do was test my original function's output for the presence of my tag (~~#), and it wasn't present, simply recurse parent() until I found it and then take that node.

Thanks!