0

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!

2
  • Is there an order that you want to use them in? LEPS first, then fall back onto EPS, then on to JPG, etc? Commented Jan 14, 2015 at 18:58
  • Currently it's LEPS first, EPS second, no third. If the project needs change, I'm sure I could adapt once I have the basic logic down. Thanks! Commented Jan 14, 2015 at 19:38

2 Answers 2

2

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>
Sign up to request clarification or add additional context in comments.

1 Comment

Working on fitting that query into my code - will report back tonight. Tested it with a parser though and I see how it works. Thanks!
2

In basic pseudo, you could, in your foreach, check your type, if it matches, store the url for later use and break out of the loop.

Something similar to

url = null
foreach node in element:
    if node->type == 'LEPS':
        url = node->url
        break
    else if node->type == 'EPS':
        url = node->url

// if url is null, no result found

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.