Reputation: 97
I try to read a XML file, show the data in a table and write the needed data into a MySQL Database so that i can later extract the data as CSV.
In the XML are a set of data that all have the same name.
Each product has a different amount of < props> (max 20) and I want to check if a element < props> exit or not. Right now I get all 'data' from props.
it's difficult for me to explain so i will show the nested elements with the specific data. EDIT: Now the complete Data of a Product.
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product>
<id>1</id>
<artnr>3009000555</artnr>
<title>product</title>
<description>Some long text</description>
<brand>
<id>458</id>
<title>Brand</title>
</brand>
<date>11-05-2015</date>
<modifydate>07-05-2016</modifydate>
<variants>
<variant>
<id>35021</id>
<type></type>
<subartnr>3009000555</subartnr>
<ean>85252000555</ean>
<stock>Y</stock>
</variant>
</variants>
<price>
<currency>EUR</currency>
<b2b>9.39</b2b>
<b2c>16.95</b2c>
<vatnl>21</vatnl>
<vatde>19</vatde>
<discount>N</discount>
</price>
<categories>
<category>
<cat>
<id>1</id>
<title>Maincat</title>
</cat>
<cat>
<id>182</id>
<title>Subcat</title>
</cat>
</category>
</categories>
<measures>
<length>4.00</length>
<weight>243</weight>
<packing>10x9x10</packing>
</measures>
<properties>
<prop>
<propid>25</propid>
<property>Farbe</property>
<valueid>208</valueid>
<value>Weiß</value>
</prop>
<prop>
<propid>41</propid>
<property>Geeignet für</property>
<valueid>229</valueid>
<value>Unisex</value>
</prop>
<prop>
<propid>43</propid>
<property>Verpackung</property>
<valueid>236</valueid>
<value>Einzelhandelverpackung (Karton)</value>
</prop>
<prop>
<propid>54</propid>
<property>Gesamturteil</property>
<valueid>289</valueid>
<value>5</value>
</prop>
<prop>
<propid>70</propid>
<property>Garantie</property>
<valueid>326</valueid>
<value>Ja</value>
</prop>
<prop>
<propid>71</propid>
<property>Art der Garantie</property>
<valueid>328</valueid>
<value>Good Warranty Service</value>
</prop>
</properties>
<material>
<id>101</id>
<title>Keramik</title>
</material>
<popularity>3</popularity>
<pics>
<pic>3009000022.jpg</pic>
<pic>3009000022_2.jpg</pic>
</pics>
</product>
<product>
Here is what i have right now but as i said before, i get also non existing props as empty data. e.g ::7, Edit. Now my whole code. This product has only 7 < props> other have 9 oder 15 or what ever. So i need only shown existing props. but yet i get all from prop[0] to prop[19] even if they not exist.
<html>
<table id="mytable">
<thead>
<tr>
<th>Artnr</th>
<th>Name</th>
<th>Beschreibung</th>
<th>Hersteller</th>
<th>EAN</th>
<th>Vorrat</th>
<th>Preis EK</th>
<th>Preis VK</th>
<th>Sonderangebot</th>
<th>Kategorie</th>
<th>Eigenschaften</th>
<th>Bild URL</th>
</tr>
</thead>
<tbody>
<?php
$url = ('http://somdom.com/test1.xml');
$xml = simplexml_load_file( urlencode($url), null, true);
$kommaleerz = ', ';
$doppelpunkt = ':';
$bildaddy = 'http://somedom.com/img/product_pic/500/';
foreach ( $xml->product as $prods ) :?>
<tr>
<td><?php echo $prods->artnr; ?></td>
<td><?php echo $prods->title; ?></td>
<td><?php echo $prods->description; ?></td>
<td><?php echo $prods->brand->title; ?></td>
<td><?php echo $prods->variants->variant->ean; ?></td>
<td><?php echo $prods->variants->variant->stock; ?></td>
<td><?php echo $prods->price->b2b; ?></td>
<td><?php echo $prods->price->b2c; ?></td>
<td><?php echo $prods->price->discount; ?></td>
<td><?php echo $prods->categories->category->cat[1]->title; ?></td>
<td><?php if (isset($prods->properties->prop)) {echo $prods->properties->prop[0]->property . $doppelpunkt . $prods->properties->prop[0]->value .$doppelpunkt .'1' .$kommaleerz
.$prods->properties->prop[1]->property . $doppelpunkt . $prods->properties->prop[1]->value .$doppelpunkt .'2' .$kommaleerz
.$prods->properties->prop[2]->property . $doppelpunkt . $prods->properties->prop[2]->value .$doppelpunkt .'3' .$kommaleerz
.$prods->properties->prop[3]->property . $doppelpunkt . $prods->properties->prop[3]->value .$doppelpunkt .'4' .$kommaleerz
.$prods->properties->prop[4]->property . $doppelpunkt . $prods->properties->prop[4]->value .$doppelpunkt .'5' .$kommaleerz
.$prods->properties->prop[5]->property . $doppelpunkt . $prods->properties->prop[5]->value .$doppelpunkt .'6' .$kommaleerz
.$prods->properties->prop[6]->property . $doppelpunkt . $prods->properties->prop[6]->value .$doppelpunkt .'7' .$kommaleerz
.$prods->properties->prop[7]->property . $doppelpunkt . $prods->properties->prop[7]->value .$doppelpunkt .'8' .$kommaleerz
.$prods->properties->prop[8]->property . $doppelpunkt . $prods->properties->prop[8]->value .$doppelpunkt .'9' .$kommaleerz
.$prods->properties->prop[9]->property . $doppelpunkt . $prods->properties->prop[9]->value .$doppelpunkt .'10' .$kommaleerz
.$prods->properties->prop[10]->property . $doppelpunkt . $prods->properties->prop[10]->value .$doppelpunkt .'11' .$kommaleerz
.$prods->properties->prop[11]->property . $doppelpunkt . $prods->properties->prop[11]->value .$doppelpunkt .'12' .$kommaleerz
.$prods->properties->prop[12]->property . $doppelpunkt . $prods->properties->prop[12]->value .$doppelpunkt .'13' .$kommaleerz
.$prods->properties->prop[13]->property . $doppelpunkt . $prods->properties->prop[13]->value .$doppelpunkt .'14' .$kommaleerz
.$prods->properties->prop[14]->property . $doppelpunkt . $prods->properties->prop[14]->value .$doppelpunkt .'15' .$kommaleerz
.$prods->properties->prop[15]->property . $doppelpunkt . $prods->properties->prop[15]->value .$doppelpunkt .'16' .$kommaleerz
.$prods->properties->prop[16]->property . $doppelpunkt . $prods->properties->prop[16]->value .$doppelpunkt .'17' .$kommaleerz
.$prods->properties->prop[17]->property . $doppelpunkt . $prods->properties->prop[17]->value .$doppelpunkt .'18' .$kommaleerz
.$prods->properties->prop[18]->property . $doppelpunkt . $prods->properties->prop[18]->value .$doppelpunkt .'19' .$kommaleerz
.$prods->properties->prop[19]->property . $doppelpunkt . $prods->properties->prop[19]->value .$doppelpunkt .'20' .$kommaleerz
.'Material' . $doppelpunkt . $prods->material->title .$doppelpunkt .'21' ;} ?> </td>
<td><?php echo $bildaddy . $prods->pics->pic[0] . $kommaleerz
.$bildaddy . $prods->pics->pic[1] . $kommaleerz
.$bildaddy . $prods->pics->pic[2] . $kommaleerz
.$bildaddy . $prods->pics->pic[3] . $kommaleerz
.$bildaddy . $prods->pics->pic[4] . $kommaleerz
.$bildaddy . $prods->pics->pic[5] . $kommaleerz
.$bildaddy . $prods->pics->pic[6] . $kommaleerz
.$bildaddy . $prods->pics->pic[7] . $kommaleerz
.$bildaddy . $prods->pics->pic[8] . $kommaleerz
.$bildaddy . $prods->pics->pic[9] . $kommaleerz
.$bildaddy . $prods->pics->pic[10] . $kommaleerz
.$bildaddy . $prods->pics->pic[11] . $kommaleerz
.$bildaddy . $prods->pics->pic[12] . $kommaleerz
.$bildaddy . $prods->pics->pic[13] . $kommaleerz
.$bildaddy . $prods->pics->pic[14] . $kommaleerz
.$bildaddy . $prods->pics->pic[15] . $kommaleerz
.$bildaddy . $prods->pics->pic[16] . $kommaleerz
.$bildaddy . $prods->pics->pic[17] . $kommaleerz
.$bildaddy . $prods->pics->pic[18] . $kommaleerz
; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</body>
</html>
Upvotes: 0
Views: 1939
Reputation: 19512
SimpleXML implements different interfaces for the properties. If you use it like a string it will return the content of the first matching element. If you use it like a list, you can iterate all matching elements.
$products = new SimpleXmlElement($xml);
foreach ($products->product as $product) {
foreach ($product->properties->prop as $property) {
var_dump((string)$property->property);
}
}
Output:
string(5) "Farbe"
string(13) "Geeignet für"
string(10) "Verpackung"
string(12) "Gesamturteil"
string(8) "Garantie"
string(16) "Art der Garantie"
I would suggest defining an array of default values for each propid
that you like to read. The propid
should be more stable then the title and is not language specific. In the inner loop you validate that the id of the current exists in that array and assign the value
or valueid
.
foreach ($products->product as $product) {
// default values for each product property by `prodid`
$row = [
'25' => '',
'41' => ''
];
foreach ($product->properties->prop as $property) {
$id = (string)$property->propid;
if (array_key_exists($id, $row)) {
$row[$id] = (string)$property->value;
}
}
var_dump($row);
}
Output:
array(2) {
[25]=>
string(5) "Weiß"
[41]=>
string(6) "Unisex"
}
This way the result will always have the same count and order of elements.
To fetch a specific property use Xpath. For example to fetch the property with the propid
25:
foreach ($products->product as $product) {
$colors = $product->xpath('properties/prop[propid = 25]');
if (count($colors) > 0) {
var_dump((string)$colors[0]->property);
}
}
SimpleXmlElement::xpath()
will always return an array of SimpleXmlElement
objects. Validate the element count to check if the Xpath expression found a node.
DOM even allows you to fetch the scalar values directly. It will return a empty value if no node matches. The result of DOMXpath::evaluate()
depends on the expression. Location paths return a DOMNodeList
that is traversable with foreach
. A expression that results in a scalar will return the scalar value.
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('/products/product') as $product) {
$hasColor = $xpath->evaluate('count(properties/prop[propid = 25]) > 0', $product);
if ($hasColor) {
var_dump('Color:', $xpath->evaluate('string(properties/prop[propid = 25]/valueid)', $product));
}
}
Output:
string(6) "Color:"
string(3) "208"
Upvotes: 2