12

I was searching like mad and found no solution. The problem is simple.

Let's say I have 3 DIVs:

<div class="class1">
  <div class="subclass"> TEXT1 </div>
</div>

<div class="class2">
  <div class="subclass"> TEXT2 </div>
</div>

<div class="class1 class2">
  <div class="subclass"> TEXT3 </div>
</div>

So, very simple. I just want to find the TEXT3, which has BOTH class1 and class2. Using Simple HTML DOM Parser, I can't seem to get it to work.

Here's what I tried:

foreach($html->find("[class=class1], [class=class2]") as $item) {
$items[] =  $item->find('.subclass', 0)->plaintext;
}

The problem is, with

find("[class=class1], [class=class2]")

it's finding all of them, as the comma is like an OR, if I leave the comma, it's looking for nested class2 inside class1. I am just looking for an AND...

EDIT

Thanks to 19greg96 I found out that

div[class=class1 class2]

works, the problem is that it looks for exactly those two in that order. Let's say I have

<div class="class1 class2">
  <div class="subclass"> TEXT3 </div>
</div>

then it works, and if I have

<div class="class1 class2 class3">
  <div class="subclass"> TEXT3 </div>
</div>

it works when I put an asterix, as it looks for the substring:

div[class*=class1 class2]

PROBLEM

I know only that class1 and class3 is there, but maybe others and in random order. That still doesn't work. Any idea how to just look for A & B in any random order? So that

div[class=class1 class3]

works with that example?

3
  • You want specifically elements with both .class1 and .class2, or any element which has 2 or more of any class? Commented Jan 10, 2013 at 18:18
  • only elements with both .class1 and .class2 Commented Jan 10, 2013 at 18:38
  • edited: problem only solved partially Commented Jan 11, 2013 at 9:06

4 Answers 4

25

EDIT2: As this is a bug in the dom parser (tested on version 1.5), there is no simple way of doing this. Solution I could think of:

$find = $html->find(".class1");
$ret = array();
foreach ($find as $element) {
    if (strpos($element->class, 'class3') !== false) {
        $ret[] = $element;
    }
}
$find = $ret;

basically you find all the elements with class one than iterate through those elements to find the ones that have class two (in this case three).


Previous answer:

Simple answer (should work according to html spec):

find(".class1.class2")

this will look for any type of element (div,img,a etc..) that has both class1 and class2. If you want to specify the type of element to match add it to the beginning without a . like:

find("div.class1.class2")

If you have a space between the two specified classes it will match elements with both the classes or elements nested in the element with the first class:

find(".class1 .class2")

will match

<div class="class1">
  <div class="class2">this will be returned</div>
</div>

or

<div class="class1 class2">this will be returned</div>

edit: I tried your code and found that the solutions above do not work. The solution that does work however is as follows:

$html->find("div[class=class1 class2]")
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for you answer, but I tried it and it doesn't work with either example, .class1.class2 or div.class1.class2. It just finds nothing.
that is very interesting. I tried the code my self and got the same results as you did. Looking further into it.
I think I found it, but it seems to me that the fact that find(".class1.class2") doesn't work might indicate a bug in the html parser. The solution that worked for me was $html->find("div[class=class1 class2]")
Hey, please see edit above, it seems there is still one problem.
Updated answer, might be better answer somewhere but I couldn't find it.
1

You can also try this :

test.html

<h1 class="first second last">
    <p>Paragraph</p>
</h1>

Solution :

include "simple_html_dom.php";

$html = file_get_html('test.html');
$h1 = $html->find('h1');
foreach ($h1 as $h1) {
    $h1Class = ($h1->class);
    if($h1Class == 'first second last'){
        $item['test'] = 'success';
    }else{
        $item['test'] = 'fail';
    }
    $ar[] = $item;
}
echo "<pre>";
print_r($ar);

Comments

0

$html->find(div[class=classname1], div[class=classname2]);

or

$html->find(div.classname1, div.classname2);

1 Comment

This is what worked for me - looking for children of a defined parent. i.e. $html->find('section.whatever div.classname1,section.whatever div.classname2')
0

I had thought simple html dom let you do:

$html->find(".class1.class2")

But I guess not. You can switch to this library if you want that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.