PHP: Check if XML node exists with attribute

I can’t seem to figure this one out. I have the following XML file:

<?xml version="1.0" encoding="UTF-8"?>
<targets>
  <showcases>
    <building name="Big Blue" />
    <building name="Shiny Red" />
    <building name="Mellow Yellow" />
  </showcases>
</targets>

I need to be able to test whether or not a <building> node exists with a given name. Everything I seem to find on Google tells me to do something like the following:

$xdoc->getElementsByTagName('building')->item(0)->getAttributeNode('name')

… but if I understand that correctly, doesn’t that only test the first <building> node? item(0)? Do I need to use XQuery for this?

I’d appreciate some help! Thanks!

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

I’d suggest the following (PHP using ext/simplexml and XPath):

$name = 'Shiny Red';
$xml = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?>
<targets>
  <showcases>
    <building name="Big Blue" />
    <building name="Shiny Red" />
    <building name="Mellow Yellow" />
  </showcases>
</targets>');
$nodes = $xml->xpath(sprintf('/targets/showcases/building[@name="%s"]', $name);
if (!empty($nodes)) {
    printf('At least one building named "%s" found', $name);
} else {
    printf('No building named "%s" found', $name);
}

Solution 2

Okay, looks like XPath was what I wanted. Here’s what I came up with that does what I want:

<?php

$xmlDocument = new DOMDocument();

$nameToFind = "Shiny Red";

if ($xmlDocument->load('file.xml')) {
        if (checkIfBuildingExists($xmlDocument, $nameToFind)) {
        echo "Found a red building!";
    }
}

function checkIfBuildingExists($xdoc, $name) {
    $result = false;
    $xpath = new DOMXPath($xdoc);
    $nodeList = $xpath->query('/targets/showcases/building', $xdoc);
    foreach ($nodeList as $node) {
        if ($node->getAttribute('name') == $name) {
            $result = true;
        }
    }
    return $result;
}

?>

Solution 3

This XPath expression:

       /*/*/building[@name = 'Shiny Red']

selects the element named building the value of whose name attribute is ‘Shiny Red’ and that is a child of a child of the top element.

Probably in PHP there is a way to evaluate XPath expressions, then just evaluate the above XPath expression and use the result.

Solution 4

if I understand that correctly, doesn’t that only test the first node?

Yes. So if you want to use DOM methods like that one, you’ll have to do it in a loop. eg.:

$buildings= $xdoc->getElementsByTagName('building');
foreach ($buildings as $building)
    if ($building->getAttribute('name')==$name)
        return true;
return false;

With XPath you can eliminate the loop, as posted by Dimitre and sgehrig, but you’d have to be careful about what characters you allow to be injected into the XPath expression (eg. $name= ‘”]’ will break the expression).

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply