Search code examples
phpxmlxpathsimplexml

PHP If/Then based on XML Property Values


I have an XML file that I'm reading as a SimpleXML Element. In that file I have the following elements:

<files>
  <file>
    <type>GIF</type>
    <url>http://dl.server.com/1.GIF</url>
  </file>
  <file>
    <type>JPG</type>
    <url>http://dl.server.com/2.JPG</url>
  </file>
  <file>
    <type>TIF</type>
    <url>http://dl.server.com/1.TIF</url>
  </file>
  <file>
    <type>EPS</type>
    <url>http://dl.server.com/1.EPS</url>
  </file>
  <file>
    <type>LEPS</type>
    <url>http://dl.server.com/2.EPS</url>
  </file>
</files>

I was using a foreach() to loop through and based on the element's value, was performing an action. Now I need to look at all the files->file->type values and if "LEPS" exists, use that URL, otherwise if "EPS" exists, use that URL, and if neither exists, do nothing.

My struggle is with the XML node/element/property terms and not being able to find a way to query if files->file->type = "LEPS" is true or not. While I know how to check for attributes (isset(element['attributename']), I'm not sure how to check for an element with a specific property value.

Sorry for the elementary question!


Solution

  • You can use a predicate to check the <type> and those of the sibling file/types.

    //files/file
    [
        type='LEPS' or
        type='EPS' and not(
            following-sibling::file/type='LEPS' or
            preceding-sibling::file/type='LEPS'
        )
    ]/url
    

    Example:

    (This example uses the DOM extension rather than SimpleXML for reasons of taste. The xpath expression itself is agnostic and can be applied equally in either.)

    /* $xml = your xml string */
    
    $dom = new DOMDocument();
    $dom->loadXML($xml);
    $xpath = new DOMXPath($dom);
    
    $query = <<<'XPATH'
    //files/file
    [
        type='LEPS' or
        type='EPS' and not(
            following-sibling::file/type='LEPS' or
            preceding-sibling::file/type='LEPS'
        )
    ]/url
    XPATH;
    
    foreach ($xpath->query($query) as $node) {
        echo $dom->saveXML($node), "\n";
    }
    

    Output:

    <url>http://dl.server.com/2.EPS</url>