2009-03-31 19 views
7

Parece que no puedo entender esto. Tengo el siguiente archivo XML:PHP: compruebe si existe un nodo XML con el atributo

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

Tengo que ser capaz de probar si existe o no un nodo <building> con un nombre dado. Todo lo que parecen encontrar en Google me dice que haga algo como lo siguiente:

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

... pero si entiendo que correctamente, no que sólo prueba el primer nodo de <building>? item(0)? ¿Debo usar XQuery para esto?

¡Agradecería un poco de ayuda! ¡Gracias!

Respuesta

9

me gustaría sugerir lo siguiente (PHP usando ext/simplexml y 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); 
} 
+1

Parece que la función xpath anterior le falta un paréntesis de cierre") ". De lo contrario, gracias por el gran código –

3

De acuerdo, parece que XPath era lo que yo quería. Esto es lo que ocurrió con el que hace lo que quiero:

<?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; 
} 

?> 
1

Esta expresión XPath:

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

selecciona el elemento con nombre building el valor de cuyo name atributo es 'Shiny Red' y que es ac hild de un hijo del elemento superior.

Probablemente en PHP hay una forma de evaluar expresiones XPath, luego solo evalúa la expresión XPath anterior y usa el resultado.

1

si entiendo que correctamente, no que sólo prueba el primer nodo?

Sí. Entonces, si quieres usar métodos DOM como ese, tendrás que hacerlo en un bucle. ej .:

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

Con XPath puede eliminar el bucle, tal como fue anunciado por Dimitre y sgehrig, pero usted tiene que tener cuidado con lo que los personajes se permite que se inyecta en la expresión XPath (por ejemplo. $ name = '"]' romperá la expresión).