0

I am trying to display information from a XML file. I am using PHP and its DOMDocument class. I am attaching the xml file and the php code that i have tried.

<?xml version="1.0" encoding="utf-8" ?>
<services>
<service>
    <type>Wash</type>
    <title>Wash1</title>
    <content>Full Exterior Hand Wash</content>
    <content>Chamois dry, Pressure Clean Wheels, All Door Jambs</content>   
    <content>Plus Free Typre Gloss</content>
    <price>Hatch/Sedan:$15</price>
    <price>Others:$20</price>
</service>

<service>
    <type>Wash</type>
    <title>Wash2</title>
    <content>Wash1</content>
    <content>Plus Vacuum</content>   
    <content>Glass Cleaned(IN/OUT)</content>
    <content>Plus Free Interior Wipe</content>
    <price>Hatch/Sedan:$30</price>
    <price>Others:$38</price>
 </service>
 </services>

The php code...

    <?php
    header('Content-Type: text/html;charset=utf8');

    $xmlfile = new DOMDocument();
    $xmlfile->load('services.xml');

    $services = $xmlfile->getElementsByTagName('service');

    foreach($services as $service){
         $titles = $service->getElementsByTagName('title');
         $title = $titles->item(0)->nodeValue;
         echo "<h1>$title</h1>";

         $prices = $xmlfile->getElementsByTagName('price');

         foreach($prices as $price){
             $price = $prices->item(0)->nodeValue;
             echo "<h1>$price</h1>";
         }

     }
?>

I am only trying to output price tag values, since if that works displaying content shouldn't be a problem. Eventually i will be displaying these values in HTML structure, one by one.

Thanks for your help.

Edit: This code at the moment outputs

Wash1
Hatch/Sedan:$15
Hatch/Sedan:$15
Hatch/Sedan:$15
Hatch/Sedan:$15
Wash2
Hatch/Sedan:$15 
Hatch/Sedan:$15
Hatch/Sedan:$15
Hatch/Sedan:$15
0

3 Answers 3

2

You've got two bugs here. As pointed out in another answer, you're getting $prices from the wrong element:

$prices = $xmlfile->getElementsByTagName('price');

... should be:

$prices = $service->getElementsByTagName('price');

This doesn't fix the problem completely, however, as there's another problem. You're looping through the prices but then always returning the first <price>. You need to change this:

$price = $prices->item(0)->nodeValue;

... to this:

$price = $price->nodeValue;

The corrected code then becomes:

<?php
header('Content-Type: text/html;charset=utf8');

$xmlfile = new DOMDocument();
$xmlfile->load('services.xml');

$services = $xmlfile->getElementsByTagName('service');

foreach($services as $service){
     $titles = $service->getElementsByTagName('title');
     $title = $titles->item(0)->nodeValue;
     echo "<h1>$title</h1>";

    $prices = $service->getElementsByTagName('price');

    foreach($prices as $price){
        $price = $price->nodeValue;
        echo "<h1>$price</h1>";
    }

}

... which outputs:

Wash1

Hatch/Sedan:$15

Others:$20

Wash2

Hatch/Sedan:$30

Others:$38


You've asked when it's necessary to use item(). This basically depends on whether you're dealing with a set of nodes (a DOMNodeList) or a single node (DOMNode). getElementsByTagName returns a DOMNodeList (there might be lots of elements) so you need to select a single one, e.g.:

 $titles = $service->getElementsByTagName('title'); // Returns a `DOMNodeList` with all the titles
 $title = $titles->item(0)->nodeValue;              // Grabs just the first title

You can iterate through a DOMNodeList (it implements the Traversable) interface. When you iterate you get a DOMNode back:

$prices = $service->getElementsByTagName('price'); // Returns a `DOMNodeList`
foreach ($prices as $price) { // $price is a `DOMNode`
    // ...
}
Sign up to request clarification or add additional context in comments.

5 Comments

I changed it to the way you have done it, but it doesn't show anything. I am trying this on Microsoft Azure, could that matter in any way.
sweet it worked, the server was down for some reason and it works. I really cannot get my head around when to use item() and when not to. Could to explain a bit or perhaps an online tutorial
To clear it if i had used for($i=0, i<= $prices, $i++) and then $price=$prices->item(i)->nodeValue; would this have worked?
I've added some more explanation. Iterating by index as you suggested would also work, although you need to change the loop termination from $i <= $prices to $i < $prices->length. I'd recommend sticking to foreach though, as it's cleaner.
That helped a lot, its completely clear. Thanks!! and yup i think i will stick with foreach
1
 $prices = $xmlfile->getElementsByTagName('price');

is wrong - you should be gettung theElements of $service

$prices = $service->getElementsByTagName('price');

1 Comment

Yes this reduced the number of times Hatch/Sedan is displayed and now displays exactly 2 times, but it only displays the firs <price> tag hence only Hatch/Sedan:%15. Thanks
1

I'm not going to leave some code, but for xml manipulation I prefer SimpleXML

And a basic exmaple can be found at php site

I put some code:

$xmlstr = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<services>
<service>
    <type>Wash</type>
    <title>Wash1</title>
    <content>Full Exterior Hand Wash</content>
    <content>Chamois dry, Pressure Clean Wheels, All Door Jambs</content>   
    <content>Plus Free Typre Gloss</content>
    <price>Hatch/Sedan:$15</price>
    <price>Others:$20</price>
</service>

<service>
    <type>Wash</type>
    <title>Wash2</title>
    <content>Wash1</content>
    <content>Plus Vacuum</content>   
    <content>Glass Cleaned(IN/OUT)</content>
    <content>Plus Free Interior Wipe</content>
    <price>Hatch/Sedan:$30</price>
    <price>Others:$38</price>
 </service>
 </services>
XML;

$xml = new SimpleXMLElement($xmlstr);

foreach ($xml->service as $key) {
    echo $key->title, "\n";
    foreach ($key->price as $price) {
        echo $price, "\n";
    }
}

The output is:

Wash1
Hatch/Sedan:$15
Others:$20
Wash2
Hatch/Sedan:$30
Others:$38

1 Comment

hey thanks for that, could you explain what $xmlstr = <<<XML means; and why do they include <?php ?> in the xml file.

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.