How to Fix Get Data from XML Using PHP

Recently, I was working on a game project where I needed to fetch quests from an XML database using PHP. Everything seemed to work fine until I realized the script only fetched data when the ID was “1”. Any other quest ID, like 2 or 3? The script just fell silent and threw annoying Undefined variable notices.

So, I rolled up my sleeves, dove into the code, and here’s how I fixed it (and improved it). If you’re stuck with a similar issue, I hope this walk-through helps.

The Buggy Code I Started With

Here’s the original snippet I was using:

<?php

$xmlStringFile = '<?xml version="1.0" standalone="yes"?>
<quests>
<quest id="1">
<ID>1</ID>
<QUEST>Katakomby pod městem</QUEST>
<INFO>Asi nevíte že pod naším krásným městem je spousta tajných chodem...</INFO>
<TIME>780</TIME>
<ITEMS1></ITEMS1>
<XPMIN>180</XPMIN>
<MONEY>800</MONEY>
<LVL>1</LVL>
</quest>

<quest id="2">
<ID>2</ID>
<QUEST>Oprava zříceného mostu</QUEST>
<INFO>Před několika dny strhla záplava starý dřevěný most u radnice...</INFO>
<TIME>7200</TIME>
<ITEMS1></ITEMS1>
<XPMIN>250</XPMIN>
<MONEY>250</MONEY>
<LVL>4</LVL>
</quest>
</quests>';

$quests = new SimpleXMLElement($xmlStringFile);

// This only matches the FIRST <quest>, i.e., id="1"
if($_GET['quest'] == $quests->quest["id"]){
$quest2 = $quests->quest->QUEST;
$info_quest = $quests->quest->INFO;
$time_end = $quests->quest->TIME;
}

// Throws "Undefined variable" if condition is not met
echo $_GET['quest'] . $quest2 . $info_quest . $time_end;

?>

What Went Wrong

The line $quests->quest["id"] is the core problem. It only accesses the first <quest> element in the XML. So when I passed ?quest=2 via the URL, PHP didn’t find a match, the if block didn’t run, and the variables weren’t initialized. That led to this classic PHP warning:

Notice: Undefined variable: quest2
Notice: Undefined variable: info_quest
Notice: Undefined variable: time_end

The Fix and Improve Version

Here’s the code I rewrote to loop through each <quest> and find the one that matches the requested ID:

<?php

$xmlStringFile = '<?xml version="1.0" standalone="yes"?>
<quests>
<quest id="1">
<ID>1</ID>
<QUEST>Katakomby pod městem</QUEST>
<INFO>Asi nevíte že pod naším krásným městem je spousta tajných chodem...</INFO>
<TIME>780</TIME>
<ITEMS1></ITEMS1>
<XPMIN>180</XPMIN>
<MONEY>800</MONEY>
<LVL>1</LVL>
</quest>
<quest id="2">
<ID>2</ID>
<QUEST>Oprava zříceného mostu</QUEST>
<INFO>Před několika dny strhla záplava starý dřevěný most u radnice...</INFO>
<TIME>7200</TIME>
<ITEMS1></ITEMS1>
<XPMIN>250</XPMIN>
<MONEY>250</MONEY>
<LVL>4</LVL>
</quest>
</quests>';

$quests = new SimpleXMLElement($xmlStringFile);
$questId = $_GET['quest'] ?? null;
$found = false;

foreach ($quests->quest as $quest) {
if ((string)$quest['id'] === $questId) {
$quest2 = $quest->QUEST;
$info_quest = $quest->INFO;
$time_end = $quest->TIME;
$found = true;
break;
}
}

if ($found) {
echo "<h3>Quest ID: $questId</h3>";
echo "<p><strong>Quest:</strong> $quest2</p>";
echo "<p><strong>Info:</strong> $info_quest</p>";
echo "<p><strong>Time:</strong> $time_end seconds</p>";
} else {
echo " Quest with ID $questId not found.";
}

?>

And just like that problem solve.

Bonus Additional Feature I Added

While I was at it, I added a few more features for better usability and testing.

List All Quests

Now I can see which quests are available at any time:

echo "<h2>Available Quests</h2><ul>";
foreach ($quests->quest as $q) {
echo "<li><a href='?quest=" . $q['id'] . "'>Quest " . $q['id'] . ": " . $q->QUEST . "</a></li>";
}
echo "</ul>";

Display All Quest Details

And to make the interface friendlier, I included a detailed list of all quests:

echo "<hr><h3>All Quest Details</h3>";
foreach ($quests->quest as $q) {
echo "<div style='border:1px solid #ccc; margin-bottom:10px; padding:10px;'>";
echo "<h4>" . $q->QUEST . "</h4>";
echo "<p>" . $q->INFO . "</p>";
echo "<small>XP: {$q->XPMIN}, Money: {$q->MONEY}, Level: {$q->LVL}</small>";
echo "</div>";
}

Final Thought

If your PHP script only retrieves the first record from an XML file, chances are you’re mistakenly treating a collection of elements as a single object. To handle multiple XML nodes correctly, always use a foreach loop to iterate through the child elements. It’s also crucial to validate that your data exists before trying to use it this helps avoid undefined variable notices that often point to deeper logic issues.

Related blog posts