Joey Lemmens
Joey Lemmens

Reputation: 111

Check if XML Chain Exists in PHP

So I have the following XML chain:

$xml->assessment->outcomes_processing->outcomes->decvar->attributes()->cutvalue

XML example In Some XML-files $xml->assessment->outcomes_processing->outcomes->... does exist. But here only $xml->assessment exist.

<questestinterop>
  <assessment ident="nedolat78356769204914" title="welkom woordenschat 4">
    <qtimetadata>
      <qtimetadatafield>
        <fieldlabel>qmd_assessmenttype</fieldlabel>
        <fieldentry>Assessment</fieldentry>
      </qtimetadatafield>
    </qtimetadata>
    <section ident="nedolat78356769204915" title="Woordenschat">
      <selection_ordering>
        <selection/>
        <order order_type="Sequential"/>
      </selection_ordering>
      <item ident="QTIEDIT:FIB:34932158" title="Oefening 1">
      ...
      </item>
    </section>
  </assessment>
</questestinterop>

At the moment I am receiving the error: "Trying to get property of non-object". Which is logic because the node from outcomes doesn't exist.

So I tried a solution with isset() which obviously isn't working either.

isset($xml->assessment->outcomes_processing->outcomes->decvar->attributes()->cutvalue) ? ... : null

This gives me the same error. Because the node outcomes doesn't exist, so he throws me the error immediately. The solution could be for checking each node individually with isset(), of course with a function because otherwise I have a lot of checking to do...

This is my function, which is failed to work because the string '->' could not be processed as php code:

// xml: xml structure form SimpleXML
// chain: assessment->outcomes_processing->outcomes->decvar->attributes()->cutvalue
function checkIfXMLChainExists($xml, $chain) {
  $xmlChain = '';
  $i = 0;
  $nodes = explode('->', $chain);
  $numItems = count($nodes);

  // experimenting with eval() to treat '->' as ->; failed to work
  $a = '$xml->assessment->outcomes_processing';
  $t = eval($a);
  echo $t;
  print_r($t);

  foreach ($nodes as $node) {
    $xmlChain .= '->' . $node;

    if (isset($xml->$xmlChain)) { // Node exists
      if ($i+1 == $numItems) {
        return $xml->$xmlChain;
      }
    } else { // Node does not exists
      return 'does not exist';
    }
    $i++;
  }

Does anyone has some ideas because I don't have any inspiration at the moment :(

Thanks in advance

Upvotes: 0

Views: 409

Answers (1)

DaveRandom
DaveRandom

Reputation: 88697

Returns the data referenced by the chain, or NULL if it doesn't exist.

function getDataIfExists () {

  // We accept an unknown number of arguments
  $args = func_get_args();

  if (!count($args)) {
    trigger_error('getDataIfExists() expects a minimum of 1 argument', E_USER_WARNING);
    return NULL;
  }

  // The object we are working with
  $baseObj = array_shift($args);

  // Check it actually is an object
  if (!is_object($baseObj)) {
    trigger_error('getDataIfExists(): first argument must be an object', E_USER_WARNING);
    return NULL;
  }

  // Loop subsequent arguments, check they are valid and get their value(s)
  foreach ($args as $arg) {
    $arg = (string) $arg;
    if (substr($arg, -2) == '()') { // method
      $arg = substr($arg, 0, -2);
      if (!method_exists($baseObj, $arg)) return NULL;
      $baseObj = $baseObj->$arg();
    } else { // property
      if (!isset($baseObj->$arg)) return NULL;
      $baseObj = $baseObj->$arg;
    }
  }

  // If we get here $baseObj will contain the item referenced by the supplied chain
  return $baseObj;

}

// Call it like this:
$subObj = getDataIfExists($xml, 'assessment', 'outcomes_processing', 'outcomes', 'decvar', 'attributes()', 'cutvalue');

Upvotes: 1

Related Questions