Autor Zpráva
lokix
Profil
Zdravím všechny na fóru,

mám na Vás dotaz, radu či postup jak přečíst z xml souboru kde jsou produkty s klasickými popisy i obsah v atributech param. Vzorový soubor má krom klasických atributů (ean, img, price, tad...) i atributy param_name ve kterých je ještě param ze kterého chci dostat udaje do db. Script dole umožňuje co chci až právě na ty param-y. Ty nejsou nijak odlišeny: <param>sklo</param><param>kulatý</param>atd... Zkoušel jsem pod-foreach další: foreach ($xml->SHOPITEM->PARAM[1]->VAL as $v3) {$param2 = $v3;} ... foreach ($xml->SHOPITEM->PARAM[11]->VAL as $v13) {$param12 = $v13;} ale do db se k údajům uloží sice všechny správně ale jen z 1 řádku. Snad jsem problém popsal dost podrobně a najde se zde někdo kdo by poradil či popostrčil. Předem momc díky za jakýkoliv nápad.

foreach ($xml->SHOPITEM as $v) {
$produkt = htmlspecialchars($v->PRODUCT, ENT_QUOTES);
$ean = $v->EAN;
$url = $v->URL;
$price = $v->PRICE;
$vat = $v->VAT;
$delivery = $v->DELIVERY_DATE;
$img = $v->IMGURL;
$img2 = $v->IMGURL[1];
$img3 = $v->IMGURL[2];
$img4 = $v->IMGURL[3];
$img5 = $v->IMGURL[4];
$cattext = $v->CATEGORYTEXT;
$manufacturer = $v->MANUFACTURER;
foreach ($xml->SHOPITEM->PARAM[0]->VAL as $v2) {$param = $v2;}
/*
foreach ($xml->SHOPITEM->PARAM[1]->VAL as $v3) {$param2 = $v3;}
foreach ($xml->SHOPITEM->PARAM[2]->VAL as $v4) {$param3 = $v4;}
foreach ($xml->SHOPITEM->PARAM[3]->VAL as $v5) {$param4 = $v5;}
foreach ($xml->SHOPITEM->PARAM[4]->VAL as $v6) {$param5 = $v6;}
foreach ($xml->SHOPITEM->PARAM[5]->VAL as $v7) {$param6 = $v7;}
foreach ($xml->SHOPITEM->PARAM[6]->VAL as $v8) {$param7 = $v8;}
foreach ($xml->SHOPITEM->PARAM[7]->VAL as $v9) {$param8 = $v9;}
foreach ($xml->SHOPITEM->PARAM[8]->VAL as $v10) {$param9 = $v10;}
foreach ($xml->SHOPITEM->PARAM[9]->VAL as $v11) {$param10 = $v11;}
foreach ($xml->SHOPITEM->PARAM[10]->VAL as $v12) {$param11 = $v12;}
foreach ($xml->SHOPITEM->PARAM[11]->VAL as $v13) {$param12 = $v13;} 
*/
$qry = "INSERT into product (`product`, `ean`, `url`, `price`, `vat`, `delivery_date`, `img_url`, `img_url2`, `img_url3`, `img_url4`, `img_url5`, `category_text`, `manufacturer`, `urceni`, `cifernik`, `reminek`, `pouzdro`, `luminiscence`, `funkce`, `tvar_pouzdra`, `vodotesnost`, `rozmery`, `styl`, `typ_strojku`, `sklo`) values ('$produkt', '$ean', '$url', '$price', '$vat', '$delivery', '$img', '$img2', '$img3', '$img4', '$img5', '$cattext', '$manufacturer', '$param', '$param2', '$param3', '$param4', '$param5', '$param6', '$param7', '$param8', '$param9', '$param10', '$param11', '$param12')";
$ret=mysql_query($qry) or die (mysql_error()); 
  } 
Tori
Profil
lokix:
zkoušel jsem pod-foreach další: [...] ale do db se k údajům uloží sice všechny správně ale jen z 1 řádku.
Asi byste měl na ř.15 místo foreach ($xml->SHOPITEM->PARAM[0]->VAL as $v2) použít foreach ($v->PARAM[0]->VAL as $v2), abyste pokaždé pracoval s tímtéž produktem, jako ve vnějším foreach.

K ukládání: Máte možnost ovlivnit podobu toho XML? (Abyste např. měl <param type="barva">zelená</param> <param type="tvar_pouzdra">kulaté</param> ...)
I v současném stavu by to ale mělo jít zapsat jednodušeji. Zkuste něco takového:

// místo řádků 15-30 včetně
$params = $v->PARAM;
// array_walk($params, 'mysql_real_escape_string'); // funguje jen pokud $params je pole, nikoli objekt
$qry = "INSERT into product (`product`, `ean`, `url`, `price`, `vat`, `delivery_date`, `img_url`, `img_url2`, `img_url3`, `img_url4`, `img_url5`, `category_text`, `manufacturer`, `urceni`, `cifernik`, `reminek`, `pouzdro`, `luminiscence`, `funkce`, `tvar_pouzdra`, `vodotesnost`, `rozmery`, `styl`, `typ_strojku`, `sklo`) values ('$produkt', '$ean', '$url', '$price', '$vat', '$delivery', '$img', '$img2', '$img3', '$img4', '$img5', '$cattext', '$manufacturer', '$params[0]', '$params[1]', '$params[2]', '$params[3]', '$params[4]', '$params[5]', '$params[6]', '$params[7]', '$params[8]', '$params[9]', '$params[10]', '$params[11]')";
$ret = mysql_query($qry) or die (mysql_error()); 
(nevím, co používáte na parsování XML, možná se tedy pletu a fungovat to nebude, nevím)
lokix
Profil
Tori:
Moc děkuji "opět" za radu. XML parsuji přes simplexml a níže je celý script, který funguje se už blíží té funkční podobě. Nyní to ukládá tak jak má, ale z ostrého xml jsem zjistsil, že param-ů bude mít každý produkt různě což je hrůza. Podobu ovlivnit nemůžu je to od velkoskladu a já to potřebuji "pouze" importovat. Pod kódem přikládám vzorové xml, ale jak jsem psal nebudu znát dopředu počet param-ů takže max je jich 12, ale někde jen 9. Pokud můžete Tori byl bych rád za nakopnutí či pomoc.


Script
require_once "/inc/config/config.inc.php"; // připojení db
$xml = simplexml_load_file("ukazka.xml"); // načten í xml

foreach ($xml->SHOPITEM as $v) {
$produkt = htmlspecialchars($v->PRODUCT, ENT_QUOTES);
$ean = $v->EAN;
$url = $v->URL;
$price = $v->PRICE;
$vat = $v->VAT;
$delivery = $v->DELIVERY_DATE;
$img = $v->IMGURL;
$img2 = $v->IMGURL[1];
$img3 = $v->IMGURL[2];
$img4 = $v->IMGURL[3];
$img5 = $v->IMGURL[4];
$cattext = $v->CATEGORYTEXT;
$manufacturer = $v->MANUFACTURER;
foreach ($v->PARAM[0]->VAL as $v2) {$param = $v2;}
foreach ($v->PARAM[1]->VAL as $v3) {$param2 = $v3;}
foreach ($v->PARAM[2]->VAL as $v4) {$param3 = $v4;}
foreach ($v->PARAM[3]->VAL as $v5) {$param4 = $v5;}
foreach ($v->PARAM[4]->VAL as $v6) {$param5 = $v6;}
foreach ($v->PARAM[5]->VAL as $v7) {$param6 = $v7;}
foreach ($v->PARAM[6]->VAL as $v8) {$param7 = $v8;}
foreach ($v->PARAM[7]->VAL as $v9) {$param8 = $v9;}
foreach ($v->PARAM[8]->VAL as $v10) {$param9 = $v10;}
foreach ($v->PARAM[9]->VAL as $v11) {$param10 = $v11;}
foreach ($v->PARAM[10]->VAL as $v12) {$param11 = $v12;}
foreach ($v->PARAM[11]->VAL as $v13) {$param12 = $v13;}
$qry = "INSERT into product (`product`, `ean`, `url`, `price`, `vat`, `delivery_date`, `img_url`, `img_url2`, `img_url3`, `img_url4`, `img_url5`, `category_text`, `manufacturer`, `urceni`, `cifernik`, `reminek`, `pouzdro`, `luminiscence`, `funkce`, `tvar_pouzdra`, `vodotesnost`, `rozmery`, `styl`, `typ_strojku`, `sklo`) values ('$produkt', '$ean', '$url', '$price', '$vat', '$delivery', '$img', '$img2', '$img3', '$img4', '$img5', '$cattext', '$manufacturer', '$param', '$param2', '$param3', '$param4', '$param5', '$param6', '$param7', '$param8', '$param9', '$param10', '$param11', '$param12')";
$ret=mysql_query($qry) or die (mysql_error()); 
    }

Vzorové xml
<SHOPITEM><ID>3</ID>
<PRODUCT>Emporio Armani Sport AR5856</PRODUCT>
<URL>http://www.hodinky-365.cz/emporio-armani-sport-ar5856-x13</URL>
<PRICE>3491.7299804688</PRICE>
<VAT>21</VAT>
<DELIVERY_DATE>0</DELIVERY_DATE>
<IMGURL>http://www.hodinky-365.cz/fotky/maxi/emporio-armani-sport-ar5856_3_1.jpg</IMGURL>
<IMGURL>http://www.hodinky-365.cz/fotky/maxi/emporio-armani-sport-ar5856_3_4.jpg</IMGURL>
<IMGURL>http://www.hodinky-365.cz/fotky/maxi/emporio-armani-sport-ar5856_3_3.jpg</IMGURL>
<IMGURL>http://www.hodinky-365.cz/fotky/maxi/emporio-armani-sport-ar5856_3_2.jpg</IMGURL>
<IMGURL>http://www.hodinky-365.cz/fotky/maxi/emporio-armani-sport-ar5856_3_5.jpg</IMGURL>
<CATEGORYTEXT>Emporio Armani | Emporio Armani Sport</CATEGORYTEXT>
<MANUFACTURER>Emporio Armani</MANUFACTURER>
<PARAM><PARAM_NAME>Určení</PARAM_NAME><VAL>Pánské</VAL></PARAM>
<PARAM><PARAM_NAME>Ciferník</PARAM_NAME><VAL>analogový</VAL></PARAM>
<PARAM><PARAM_NAME>Řemínek</PARAM_NAME><VAL>silikon</VAL></PARAM>
<PARAM><PARAM_NAME>Pouzdro</PARAM_NAME><VAL>ocel</VAL></PARAM>
<PARAM><PARAM_NAME>Luminiscence</PARAM_NAME><VAL>ručičky</VAL></PARAM>
<PARAM><PARAM_NAME>Funkce</PARAM_NAME><VAL>Stopky, Datumovka</VAL></PARAM>
<PARAM><PARAM_NAME>Tvar pouzdra</PARAM_NAME><VAL>kulatý</VAL></PARAM>
<PARAM><PARAM_NAME>Vodotěsnost</PARAM_NAME><VAL>50M</VAL></PARAM>
<PARAM><PARAM_NAME>Rozměry</PARAM_NAME><VAL>42 x 49 x 11 mm</VAL></PARAM>
<PARAM><PARAM_NAME>Styl</PARAM_NAME><VAL>sportovní</VAL></PARAM>
<PARAM><PARAM_NAME>Typ strojku</PARAM_NAME><VAL>QUARTZ - baterie</VAL></PARAM>
<PARAM><PARAM_NAME>Sklo</PARAM_NAME><VAL>minerální</VAL></PARAM></SHOPITEM>
peta
Profil
Musis nejak rozlisit, ktery je ktery. Takze to bud poskladat cyklem for/forech nebo pomoci for doplnit prazdne kolonky a spojit to pomoci implode.
Tori
Profil
lokix:
z ostrého xml jsem zjistsil, že param-ů bude mít každý produkt různě což je hrůza. Podobu ovlivnit nemůžu
V tom případě bych změnila strukturu DB a ukládala variabilní vlastnosti produktu do jiné tabulky:

product_id INT (FK)
name VARCHAR(50)
value VARCHAR(300)
- u textových polí si sám určete max.možnou velikost vkládaného řetězce.

Pak by to vypadalo asi takhle:
foreach ($xml->SHOPITEM as $v) {
    // řádky 5-17 z [#3] + INSERT produktu do DB.

    // Pak zjistíte ID vloženého produktu
    $id = mysql_insert_id(); // nebo $v->ID , jestli používáte ID z importu
    // a vložíte další vlastnosti produktu
    $sql = 'INSERT INTO product_properties (product_id, name, value) VALUES ';
    foreach ($v->PARAM as $param) {
        $sql .= '('.$id.',"'.mysql_real_escape_string($param->PARAM_NAME).'","'.mysql_real_escape_string($param->VAL).'"),';
    }
    $sql = rtrim($sql, ', ');
    if (!mysql_query($sql)) echo "<br>Chyba importu: ".mysql_error();
}
lokix
Profil
Tori:
Děkuji za další progress a návrh db se mi líbí daleko více, jen bude někde ještě něco, protože to sice uloží i do té druhé tabulky, ale jen 1 položky (name - určení, value - pánská,dámský) a pak to vypíše chybu: Chyba importu: Duplicate entry '10896' for key 'PRIMARY' samozřejmně s různými entry id.

$xml = simplexml_load_file("ukazka.xml");

foreach ($xml->SHOPITEM as $v) {
$produkt = htmlspecialchars($v->PRODUCT, ENT_QUOTES);
$ean = $v->EAN;
$url = $v->URL;
$price = $v->PRICE;
$vat = $v->VAT;
$delivery = $v->DELIVERY_DATE;
$img = $v->IMGURL;
$img2 = $v->IMGURL[1];
$img3 = $v->IMGURL[2];
$img4 = $v->IMGURL[3];
$img5 = $v->IMGURL[4];
$cattext = $v->CATEGORYTEXT;
$manufacturer = $v->MANUFACTURER;
//
$qry = "INSERT into product (`product`, `ean`, `url`, `price`, `vat`, `delivery_date`, `img_url`, `img_url2`, `img_url3`, `img_url4`, `img_url5`, `category_text`, `manufacturer`) values ('$produkt', '$ean', '$url', '$price', '$vat', '$delivery', '$img', '$img2', '$img3', '$img4', '$img5', '$cattext', '$manufacturer')";
$ret=mysql_query($qry) or die (mysql_error()); 
//
$id = mysql_insert_id(); // nebo $v->ID , jestli používáte ID z importu
    // a vložíte další vlastnosti produktu
$sql = 'INSERT INTO product_properties (product_id, name, value) VALUES ';
    foreach ($v->PARAM as $param) {
$sql .= '('.$id.',"'.mysql_real_escape_string($param->PARAM_NAME).'","'.mysql_real_escape_string($param->VAL).'"),';
    }
    $sql = rtrim($sql, ', ');
    if (!mysql_query($sql)) echo "<br>Chyba importu: ".mysql_error();
  } 
juriad
Profil
lokix:
Ukaž strukturu tabulky product_properties. Vsadím své boty, že tam máš na sloupečku product_id definovaný primární klíč PRIMARY KEY místo cizího klíče REFERENCES product (product)

koukám, že nejsem sám, kdo vsází svoje boty
lokix
Profil
juriad:
Máš pravdu, ze zvyku jsem tam dal primary key. Jak by tedy měl správně vypadat product_id?
PS. Díky za upozornění.
juriad
Profil
Buď přímo za definicí sloupečku místo PRIMARY KEY napiš REFERENCES product (product)
nebo na konec definice tabulky přidej: FOREIGN KEY (product_id) REFERENCES product (product)

Viz manuál mysql: http://dev.mysql.com/doc/refman/5.5/en/create-table.html
Cizí klíče nejsou nijak vyžadovány, stejně jako primární klíče, ale umožňují kontrolu integrity dat.
Pokud je tabulka typu MyISAM, tak databáze cizí klíče úplně ignoruje.
lokix
Profil
Moc díky za pomoc Toti a juriad, nyní to ukládá jak má.
lokix
Profil
Nerad otvírám znova toto téma,

ale kdyby se našel ještě jednou jeden dobrák a pomohl mi s tímto xml. Vše funguje s původním xml jak má, ale z jiným xml kde je zase jiná struktůra to nedokážu dát tak jak potřebuju. Navíc se chci zeptat jaká by byla optimálnější, lepší možnost postavit db. Vzorové xml je níže a mám problém dostat do db položky alter kde jich může být nepočítaně nebo žádná... Díky za každou radu.

<alters>
<alter id="7794">
<name>35</name>
<code>P29019</code>
<avaibility_h>0</avaibility_h>
<avaibility_ks>1</avaibility_ks>
<avaibility>skladem</avaibility>
</alter>
<alter id="7795">
<name>36</name>
<code>P29020</code>
<avaibility_h>0</avaibility_h>
<avaibility_ks>1</avaibility_ks>
<avaibility>skladem</avaibility>
</alter>
<alter id="7797">...

Vzorové xml:

<product id="21192">
<link>http://www.esho.cz/Lodicky/Damske-lodicky-cerne-na-platforme-lakovane</link><name>Dámské lodičky černé na platformě lakované</name>
<code>P28951</code>
<manufacturer id=""/>
<pricesource>product</pricesource>
<price>990</price>
<price_vat>990</price_vat>
<vat>0</vat>
<defimg>48536</defimg>
<avaibility_h>0</avaibility_h>
<avaibility_ks>5</avaibility_ks>
<avaibility>skladem</avaibility>
<category id="1599">Lodičky</category>
<categories>
<category id="1599" main="1">Lodičky</category>
</categories>
<description>
<p><strong>Popis:</strong></p>
<p>Dámské lodičky na platformě lakované černé.</p>
<p><em>Svršek: Syntetický materiál</em></p>
<p><em>Podšívka: Syntetický materiál</em></p>
<p><em>Stélka: Kombinace kůže a syntetického materiálu</em></p>
<p><em>Podešev: Ostatní materiál</em></p>
<p> <strong>Rozměry uvedeny níže.</strong></p></description><fulldescription><div class="popisZbozi2">
<p><strong>Velikost            Délka stélky    Výška podpatku       Celková výška</strong><br />35                           23cm                  15cm                         21cm<br />36                           24cm                  15cm                         21cm<br />37                           25cm                  15cm                         21cm<br />38                           25,5cm               15cm                         21cm<br />39                           26cm                  15cm                         21cm<br />40                           26,5cm               15cm                         21cm<br />41                           27cm                  15cm                         21cm</p>
<p> </p>
<p><strong>Výška platformy:5 cm</strong></p>
</div>
</fulldescription>
<imgs>
<img default="1" id="48536">http://www.eshop.cz/img/affil/48536-damske-lodicky-cerne-na-platforme-lakovane.jpg</img>
<img id="48439">http://www.eshop.cz/img/affil/48439-damske-lodicky-cerne-na-platforme-lakovane.jpg</img>
<img id="48440">http://www.eshop.cz/img/affil/48440-damske-lodicky-cerne-na-platforme-lakovane.jpg</img>
</imgs>
<alters>
<alter id="7794">
<name>35</name>
<code>P29019</code>
<avaibility_h>0</avaibility_h>
<avaibility_ks>1</avaibility_ks>
<avaibility>skladem</avaibility>
</alter>
<alter id="7795">
<name>36</name>
<code>P29020</code>
<avaibility_h>0</avaibility_h>
<avaibility_ks>1</avaibility_ks>
<avaibility>skladem</avaibility>
</alter>
<alter id="7797">
<name>38</name>
<code>P29022</code>
<avaibility_h>0</avaibility_h>
<avaibility_ks>2</avaibility_ks>
<avaibility>skladem</avaibility>
</alter>
<alter id="7798">
<name>39</name>
<code>P29023</code>
<avaibility_h>0</avaibility_h>
<avaibility_ks>1</avaibility_ks>
<avaibility>skladem</avaibility>
</alter>
</alters>
<attributes/>
</product>
Tori
Profil
Na to by měla být další tabulka, pro varianty produktu. Ale jestli vlastnosti jednotlivých variant ukládat do této nové tabulky anebo prolinkovat z tabulky vlastností, to asi záleží na tom, jestli pracujete s jedním typem zboží nebo ne.

Např. pokud prodáváte jenom boty a neplánujete rozšiřovat sortiment o jiné zboží, může být tabulka variant produktu denormalizovaná:
tab. zbozi
ID | název | materiál | ...
1  | botasky dámské | svršek i vnitřek kůže | 

tab. varianty_zbozi
ID | ID_zbozi | velikost | barva | ks_skladem  ...
1 | 1 | 35 | hnědá s bílými pruhy | ..
2 | 1 | 36 | hnědá s bílými pruhy |
3 | 1 | 36 | černá s bílými pruhy |

Ale pokud by to mělo být univerzálnější, pro různé druhy zboží, tak budou vlastnosti jednotlivých variant uložené jinak, např. nějak takhle:
tab. zbozi
ID | název ....
1 | botasky dámské |
2 | kondenzátor tantalový |

tab. varianty_zbozi
ID | ID_zbozi | ks_skladem
1 | 1 |
2 | 1 |
3 | 1 |
4 | 2 |
5 | 3 |

tab. vlastnosti_zbozi
ID | ID_varianty | název | hodnota 
1 | 1 | velikost | 35
2 | 1 | barva | hnědá s bílými pruhy
3 | 1 | materiál | svršek i vnitřek kůže
4 | 2 | velikost | 36
5 | 2 | barva | hnědá s bílými pruhy
6 | 2 | materiál | svršek i vnitřek kůže
7 | 3 | velikost | 36
8 | 3 | barva | černá s bílými pruhy
9 | 3 | materiál | svršek i vnitřek kůže
10 | 4 | kapacita | 100n
11 | 4 | napětí | 100V
12 | 5 | kapacita | 220n
13 | 5 | napětí | 100V
lokix
Profil
Děkuji Tori toto univerzálnější (2. řešení) je to co jsem hledal. Takto jsem tedy upravil db a jsou tam teď 3 tabulky, ale chci se zeptat jak by jste upravila ještě následné zpracování xml jako u vzorového xml? #11
Tori
Profil
Tak podobně jako [#6], pseudokód:

pro každý produkt:
   - načti data produktu, ulož ho do DB a zjisti ID nového záznamu
   - pro každou variantu produktu:
       - připrav si začátek SQL pro ukládání vlastností: "INSERT INTO (sloupce) VALUES "
       - vytvoř nový záznam ve vazební tabulce (varianty_zbozi) a zjisti jeho ID
           - všechny potřebné informace o variantě přidej do SQL: " (1, 'velikost', 35), (1, 'cena', 990), "
       - z připraveného SQL odstraň čárku na konci a ulož do DB (tab. vlastnosti_zbozi)
Nejsem si jistá, jak (do které tabulky) ukládat např. cenu nebo obrázky - zrovna u bot/oblečení se může cena téhož typu lišit podle velikosti, obrázků může být několik pro různobarevné varianty... Ale to odhadnete sám, nejlíp víte s jakými daty / druhy zboží pracujete. Anebo jste chtěl konkrétní kód? Od toho v [#6] se moc neliší, jen se jinak jmenují XML prvky, princip je ale IMHO stejný.
lokix
Profil
Tori:
Moc děkuji tohle už snad dohromady dám,ale chci se Vás zeptat jestli máte čas a chuť si něco vydělat. Vím tady to nepatří, ale bylo by více projektů a já toho mám už více tak pokud chcete a můžete šlo by se domluvit na nějaké formě spolupráce.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: