0

I have a xml file in this format:

<?xml version="1.0" encoding="ISO-8859-1"?>
<adp_report name="Average Draft Position - Mixed 5x5" rundate="2013-01-29 17:22:10.0" begin="2013-01-26" end="2013-01-29" draftcount="126">
     <player id="500736" name="Mike Trout" position="OF" team="ANA" adp="1.66" early="1" late="4" selections="126" />
     <player id="291154" name="Ryan Braun" position="OF" team="MIL" adp="2.01" early="1" late="4" selections="126" />
     <player id="213968" name="Miguel Cabrera" position="3B" team="DET" adp="2.55" early="1" late="4" selections="126" />
</adp_report>

I need to load this into php where I will be able to access it by finding the name attribute and what the corresponding adp is. I am using it to perform some calculations and insert the results into a table that is being called from a MYSQL database. This is what I have so far:

$url = '...some url';
$xml = simplexml_load_file($url);    
while($row = mysqli_fetch_array($resultbat, MYSQLI_ASSOC))
  {
       echo "<td>" . $row['NAME'] . "</td>";
       ...print out some more player data from database...

       foreach($xml->player as $player)
            {
                $attr = $player->attributes();

                if($attr['name'] == $row['NAME']) //$row['NAME'] is the players name from my database
                {
                    $adp = (float) $attr['adp'];
                    $early = (int) $attr['early'];      

                    $stdev = -0.42+0.42*($adp-$early);
                    if($stdev<0)
                        $stdev = 1;
                    $chance =number_format(((1-NORMDIST($pickNumber,$adp,$stdev,TRUE))*100), 0);

                  echo "<td class='adp'>".$adp."</td>";
                  echo "<td class='chance'>".$chance."%</td>";
                  break;
                }
            }
}

This takes a while to process because I'm going through every row in my player database, then using foreach to look through the xml file and if I find a match I do the calculations. I have to imagine there is a more efficient way to go about this. Thanks in advance.

1
  • I think the right thing to do is to build a list of the player names form the XML and then query the database with an IN clause. You're doing this in the reverse order, which requires querying unneeded data from the database and going through the entire table. That's not a scalable approach. Commented Jan 30, 2013 at 7:55

2 Answers 2

1

You could use XPath (see: SimpleXMLElement::xpath() and XPath documentation). So, instead of your foreach loop, this:

$player = $xml->xpath('//player[@name="' . $row['NAME'] . '"]');
if (is_array($player) && count($player)) {
    $player = $player[0];
} else {
    continue; // not found
}
$attr = $player->attributes();
// and so on...
Sign up to request clarification or add additional context in comments.

Comments

0

I'd pre-process the XML file to an associative-array (user-id/user-name => properties);

$url = '...some url';
$xml = simplexml_load_file($url);

$players = array();

foreach($xml->player as $player) {
    $attr = $player->attributes();

    // cast the SimpleXMLElement to a string
    $username = (string) $attr['name'];
    $players[$username] = $attr;
}

Then retrieve the data from the database and match the results from XML

while($row = mysqli_fetch_array($resultbat, MYSQLI_ASSOC)) {
     if(!array_key_exists($row['NAME'], $players)) {
          // player was not found in the XML
          continue;
     }

     // get the player's properties by matching the 'name'
     $player_stats = $players[$row['NAME']];

     // here, process player_stats

}

However, your code assumes the player-name to be unique, it may be possible that multiple players share the same name (this problem was already present in your current code)

2 Comments

when I tested the first part of the code I get the following error: Warning: Illegal offset type for the $players[$attr['name']] = $attr; line. Am I missing something?
@rodzilla I suspect that $attr['name'] will produce a SimpleXMLelement object, not an actual string. This can be fixed by casting it to a string. I updated my code with this fix, haven't been able to test it though

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.