Timon Knigge
Timon Knigge

Reputation: 304

Only the first element is being read while processing XML in PHP

I'm having some trouble with reading XML files in PHP. I'm not very skilled in PHP, so I use this code snippet: Article.

This is the XML file I'm trying to read: http://pastebin.com/2dtMp5VH

<?xml version="1.0" encoding="UTF-8"?>
<contentdata>
    <Games>
    <numberof>2</numberof>
        <nameof>
            <n1>Game1</n1>
            <n2>Game2</n2>
        </nameof>
     </Games>
     <Software>
    <numberof>1</numberof>
        <nameof>
            <n1>Software1</n1>
        </nameof>
     </Software>
</contentdata>

This is my PHP script, based on the article I gave: http://pastebin.com/d29ejxSJ

$objDOM = new DOMDocument(); 
$objDOM->load("content.xml");
$note = $objDOM->getElementsByTagName("Games"); 

foreach( $note as $value ) 
{ 
    $numberof = $value->getElementsByTagName("numberof"); 
    $numberof_  = $numberof->item(0)->nodeValue; 
    echo($numberof_." games found!<br />");

    $numberof = (integer)$numberof_;
    $nameof = $value->getElementsByTagName("nameof");
    $i = 1;
    foreach($nameof as $value2)
    {
        $n = (string)$i;
        $nameof_[$i] = $value2->getElementsByTagName("n".$n);
        $nameof_[$i] = $nameof_[$i]->item(0)->nodeValue;
        echo(((string)$i).": ".$nameof_[$i]."<br />");
        $i++;
    }
} 

The output should be this:
2 games found!
1: Game1
2: Game2

However, for some reason it only outputs the following:
2 games found!
1: Game1

What is wrong with my code? How to solve this?

Upvotes: 0

Views: 1367

Answers (6)

Sorin Trimbitas
Sorin Trimbitas

Reputation: 1497

Take a look over SimpleXML function: simplexml_load_string.

Upvotes: 0

Rick van der Zwet
Rick van der Zwet

Reputation: 951

You second foreach is wrong as it only evaluate after the nameof entries in Games which is currently one entry.

You will need to use your nameof_ to iterate in your case:

$objDOM = new DOMDocument(); 
$objDOM->load("content.xml");
$note = $objDOM->getElementsByTagName("Games"); 

foreach( $note as $value ) 
{ 
    $numberof = $value->getElementsByTagName("numberof"); 
    $numberof_  = $numberof->item(0)->nodeValue; 
    echo($numberof_." games found!<br />\n");

    $numberof = (integer)$numberof_;
    $nameof = $value->getElementsByTagName("nameof");
    for ($i = 1; $i <= $numberof_; $i++)
    {
        $n = (string)$i;
        $nameof_[$i] = $nameof->item(0)->getElementsByTagName("n".$n);
        $nameof_[$i] = $nameof_[$i]->item(0)->nodeValue;
        echo(((string)$i).": ".$nameof_[$i]."<br />\n");
    }
} 

As a advisory take a closer look at your data definition -like @jon_darkstar suggested as well- it does not look very XMLish (eg easy automatic parseble).

If you for example use this format, parsing will be more easy:

<?xml version="1.0" encoding="utf-8"?>
<contentdata>
  <Games>
    <item name="Game1" />
    <item name="Game2" />
  </Games>
  <Software>
    <item name="Software1" />
  </Software>
</contentdata>

Which you can than parse using

$objDOM = new DOMDocument();
$objDOM->load("content.xml");
$gamesElements = $objDOM->getElementsByTagName("Games");

foreach ($gamesElements as $gamesElement)
{
    $itemElements = $gamesElement->getElementsByTagName("item");
    echo ($itemElements->length . " games found!<br />\n");

    $i = 1;
    foreach ($itemElements as $itemElement) {
       $name = $itemElement->attributes->getNamedItem('name')->nodeValue;
       echo("$i: $name<br />\n");
       $i++;
    }
}

Upvotes: 0

BigFatBaby
BigFatBaby

Reputation: 1510

It seems like your problem is iterating through all the child elements in the <nameof> tag.

try the following:

foreach($nameof as $node){
    foreach($node->childNodes as $child) {
       echo '<br/>Node Name: '.$child->nodeName.' Node Value: '.$child->nodeValue.'<br/>';
    }
}

instead of your last foreach statement and observe the output

Upvotes: 0

Akarun
Akarun

Reputation: 3350

Like @chris sayd, I think you make the second foreach on the bad node. Your second foreach target : nameof and not his content (n1, n2, ...)

With Simple XML:

$Games = $value->getElementsByTagName("nameof")->children();
foreach($Games as $value2)
{
   // Your code to parse <nX>
}

Upvotes: 1

Chris
Chris

Reputation: 7855

In $value you are keeping a reference of the Games node which containes just one single nameof node. Then later you make

foreach($nameof as $value2)

which will be executed exactly one time because there is only one nameof node in it. Your $i will stay 1 so only game one will be printed out.

What you need to do is selecting all the "nX" nodes and iterating through them but not through the nameof nodes because theres only one of it. Alternatively you can change the for loop so that you iterate exactly as much as is written in numberof.

Upvotes: 0

jon_darkstar
jon_darkstar

Reputation: 16768

We need to see your XML, to really help with this BUT...

I think you might be confusing elements and attributes. In brief, XML is composed like this

<tagname attr1=5 attr2='arf'> BODY HERE </tagname>

In your case, I don't believe numberof and nameof are elements at all. They seem to be attributes belonging to Games elements.

Use echoes or var_dump to show the contents of variables like $notes and $numberof I think you'll find they don't contain what you're expecting.

Upvotes: 0

Related Questions