0

I have a feed with several products in it, but the fields are not known. I want to display a "tree structure" from the file with PHP.

THe XML looks like following:

<products>
  <product id="1">
    <title>Title of product 1</title>
    <weight measure="kg">4000</weight>
    <specs>
       <spec name="spec1">
       <value>value spec 1</value>
       <spec name="spec2">
       <value>value spec 2</value>
    </specs>
  </product>
  <product id="2">
    <title>Title of product 2</title>
    <weight measure="kg">10000</weight>
    <specs>
       <spec name="spec1">
       <value>value spec 1</value>
       <spec name="spec2">
       <value>value spec 2</value>
       <spec name="spec3">
       <value>value spec 3</value>
    </specs>
  </product>
</products>

I'd like my PHP to display something like this so that I can insert these values in the database:

Product: 1
title: Title of product 1
weight: 4000
spec1: value spec 1
spec2: value spec 2

Product: 2
title: Title of product 2
weight: 10000
spec1: value spec 1
spec2: value spec 2
spec3: value spec 3

As mentioned, the feeds are differently every time, with different fields. Thats making it more difficult to me..

$xml = simplexml_load_file($feedURL);
foreach($xml->product as $products) {
    echo '>.'.$products[ID].'<br>';
    foreach($products->children() as $properties){
        echo $properties[name].': '.$properties->value.'<br>';
        foreach($properties->children() as $aspects){
            echo '--->'.$aspects[name].': '.$aspects->value.'<br>';
        }
    }
}

It does not work at this moment. How could I fix this?

7
  • Consider using the built in DOM parser. $dom = new domDocument; $dom->loadHTML($xml); Commented Dec 31, 2018 at 0:21
  • Not sure how to do this. I am not familiar with the DOM parser. How do I fetch the values in $dom ? Commented Dec 31, 2018 at 0:26
  • There are tons of tutorials on it. It's a pretty well documented feature. There's also a third party tool called Simple DOM Parser that might be better for you. Commented Dec 31, 2018 at 0:28
  • Thanks, this is very helpfull! I will look for Simple DOM Parser. Many thanks. Commented Dec 31, 2018 at 0:29
  • "It does not work" What does that mean to you? Because it doesn't mean anything to us. What output do you get? What errors? Commented Dec 31, 2018 at 1:16

2 Answers 2

1

The problem is i've copied your XML file and it's not really valid.

http://www.xmlvalidation.com/index.php?id=1&L=2

You can use the validator and when you load your file you should get some errors in PHP that your XML file is not valid. And when you look at your XML your "spec" is not really correct.

<spec name="spec1">
<value>value spec 1</value>

<spec name="spec2">
<value>value spec 2</value>

<spec name="spec3">
<value>value spec 3</value>

Your "spec" tag is not closed and that causes some errors. You you have to close the spec tag or make it as a single tag.

<spec name="spec2">
    <value>value spec 2</value>
</spec>

You should resolve your problems first. Then you should be able to get the correct values. Otherwise when you enable your php errors you can see the errors that the xml is not valid.

Sign up to request clarification or add additional context in comments.

Comments

1

Firstly, there is an issue with your XML, in that your <spec> tags are not properly closed, so simplexml_load_string won't actually load the XML. You can work around that by using preg_match e.g.

$xmlstr = file_get_contents($feedURL);
$xml = simplexml_load_string(preg_replace('/(<spec [^>]+)>/', '$1 />', $xmlstr));

This converts something like:

<spec name="spec1">

to

<spec name="spec1" />

Then you have some other issues with your code.

  1. You are using unquoted strings e.g. ID, name
  2. To get the name of a SimpleXMLElement you use $element->getName(), not $element['name']
  3. To get the value of a SimpleXMLElement you simply cast it to the appropriate type e.g. (string)$element not $element->value

Enabling error reporting would have shown up a lot of these problems before you asked the question. Making all those corrections to your code gives this result:

foreach($xml->product as $products) {
    echo 'Product: '.$products['id']."\n";
    foreach($products->children() as $properties){
        if (!count($properties->children())) echo $properties->getName().': '.(string)$properties."\n";
        foreach($properties->children() as $aspects){
            if ($aspects->getName() == 'spec')
                echo $aspects['name'].': ';
            else
                echo (string)$aspects . "\n";
        }
    }
}

Which gives the following output:

Product: 1 
title: Title of product 1 
weight: 4000 
spec1: value spec 1 
spec2: value spec 2 
Product: 2 
title: Title of product 2 
weight: 10000 
spec1: value spec 1 
spec2: value spec 2 
spec3: value spec 3

Demo on 3v4l.org

Comments

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.