John Smith
John Smith

Reputation: 1780

XPath return null if attribute not found?

I'm using an XPath query to find attribute values. However, I want to go through each div and if the attributes are not found, return nothing. Is there a way to do this?

HTML:

<div id="a" class="a">text</div>
<div>text</div>
<div id="b" class="b">text</div>

XPath:

$values = $XPath->query('//div/@id | //div/@class');

Result:

array('a', 'a', 'b', 'b');

Desired Result:

array('a', 'a', '', '', 'b', 'b');

As of now, I'm kind of in XPath already, and I would like to stay in this direction for right now.

Upvotes: 0

Views: 1648

Answers (2)

hakre
hakre

Reputation: 197775

I just add an additional answer to provide my own wording and that you can easily see that what @hek2gml suggest is sensible.

An xpath query can only return what is in the document already. So you can not insert non-existing nodes in the same query.

So you need to do it like your describe what you want to do:

I want to go through each div and if the attributes are not found, return nothing.

So per each match of a div, get both attribute values, empty attribute values incl.:

$html = <<<BUFFER
<div id="a" class="a">text</div>
<div>text</div>
<div id="b" class="b">text</div>
BUFFER;

$xml = simplexml_import_dom(@DOMDocument::loadHTML($html));

$divs = $xml->xpath('/*/body/div');

$reduce = function(array $array, SimpleXMLElement $div) {
    $array[] = (string) $div['id'];
    $array[] = (string) $div['class'];
    return $array;
};

$values = array_reduce($divs, $reduce, []);

print_r($values);

The output is as expected:

Array
(
    [0] => a
    [1] => a
    [2] => 
    [3] => 
    [4] => b
    [5] => b
)

Upvotes: 2

hek2mgl
hek2mgl

Reputation: 158010

Why not just selecting all <div> elements and the use DOMElement::getAttribute() to obtain the attibute values? Note that this method will return an empty string if the current element didn't has the attribute which is requested. (What should actually what you want).

Try this:

$html = <<<EOF
<div id="a" class="a"></div>
<div></div>
<div id="b" class="b"></div>
EOF;

$doc = new DOMDocument();
$doc->loadHtml($html);
$selector = new DOMXpath($doc);

$result = array();
foreach($selector->query('//div') as $div) {
    $result []= $div->getAttribute('id');
    $result []= $div->getAttribute('class');
}

var_dump($result);

Output:

array(6) {
  [0] =>
  string(1) "a"
  [1] =>
  string(1) "a"
  [2] =>
  string(0) ""
  [3] =>
  string(0) ""
  [4] =>
  string(1) "b"
  [5] =>
  string(1) "b"
}

Upvotes: 3

Related Questions