Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [XML][PHP] Przetwarzanie katalogu, wyciąganie danych
flipp
post 7.07.2013, 13:24:33
Post #1





Grupa: Zarejestrowani
Postów: 7
Pomógł: 0
Dołączył: 30.03.2013

Ostrzeżenie: (0%)
-----


Witam,
od kilku dni szukam, czytam i testuję. Mam do przetworzenia katalog, który dostałem w pliku XML (cały waży ok. 5 mb, zawiera kilkaset produktów opisanych w 110 tys. linii). Obecnie jestem na etapie SimpleXML, ale nie wiem, czy idę w dobrą stronę i stąd ten post.

Skrypt wyszukuje produkt według jego unikalnego ID, następnie wyciąga potrzebne dane produktu z odpowiednich elementów (identyfikowanych według ich atrybutu), wyświetla to w przeglądarce (docelowo ma zapisywać do bazy SQL).

Poniżej zamieszczam mój roboczy skrypt:
  1. <?php
  2. error_reporting(E_ALL|E_STRICT);
  3. ini_set('display_errors', '1');
  4.  
  5. $katalog = simplexml_load_file('przyklad.xml');
  6. $szukaneid = 1071370015;
  7.  
  8. //szuka produktu po ID
  9. foreach($katalog->country_product as $produkt){
  10. if($produkt->product->attributes()->id == $szukaneid){
  11. echo 'Produkt o id: ' . $szukaneid . ' to: ' . $produkt->product->name . '<br/>';
  12.  
  13. echo '<br/>Opis:<br/>';
  14.  
  15. foreach($produkt->contents->content as $wyswietl1){
  16. foreach($wyswietl1->nomenclatura as $wyswietl2){
  17. if($wyswietl2->attributes()->key == "Benefit"){
  18. echo $wyswietl1->headline;
  19. echo $wyswietl1->text . '<br/>';
  20. }
  21. }
  22. }
  23.  
  24. echo $produkt->daily_ration_csv->daily_ration_head_text;
  25. echo '<br/>';
  26. echo $produkt->daily_ration_csv->daily_ration_table;
  27. echo '<br/>';
  28.  
  29. //Sklad
  30. echo 'Sklad:<br/>';
  31. foreach($produkt->{'ingredient-amounts'}->ingredient_amount as $skladnik1){
  32. if($skladnik1->ingredient->ingredient_section->attributes()->name_key == "analysis_table"){
  33. echo $skladnik1->ingredient->name;
  34. echo ' ';
  35. echo $skladnik1->amount;
  36. echo ' ';
  37. echo '(' . $skladnik1->unit->name . ')';
  38. echo '<br/>';
  39. }
  40.  
  41. }
  42.  
  43. echo '<br/>Mineraly:<br/>';
  44. //Mineraly
  45. foreach($produkt->{'ingredient-amounts'}->ingredient_amount as $skladnik2){
  46. if($skladnik2->ingredient->ingredient_section->attributes()->name_key == "minerals"){
  47. echo $skladnik2->ingredient->name;
  48. echo ' ';
  49. echo $skladnik2->amount;
  50. echo ' ';
  51. echo '(' . $skladnik2->unit->name . ')';
  52. echo '<br/>';
  53. }
  54.  
  55. }
  56.  
  57. echo '<br/>Witaminy:<br/>';
  58. //WITAMINY
  59. foreach($produkt->{'ingredient-amounts'}->ingredient_amount as $skladnik3){
  60. if($skladnik3->ingredient->ingredient_section->attributes()->name_key == "vitamins"){
  61. echo $skladnik3->ingredient->name;
  62. echo ' ';
  63. echo $skladnik3->amount;
  64. echo ' ';
  65. echo '(' . $skladnik3->unit->name . ')';
  66. echo '<br/>';
  67. }
  68.  
  69. }
  70. }
  71. }
  72. ?>


Przykładowy produkt z katalogu XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <country_products xsi:noNamespaceSchemaLocation="ab_files/schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  3. <country_product id="868484849">
  4. <name>Pasta KL3BL731</name>
  5. <product id="1071370015">
  6. <name>Pasta KL3BL731</name>
  7. </product>
  8. <!-- contents -->
  9. <contents>
  10. <content type="TextContent">
  11. <nomenclatura key="MetaTagsDescription" id="2028553811">
  12. <name>Meta Tags Description</name>
  13. </nomenclatura>
  14. <order_nr>2</order_nr>
  15. <text>
  16. <![CDATA[Some meta tags]]>
  17. </text>
  18. </content>
  19. <content type="ImageParagraphContent">
  20. <nomenclatura key="Benefit" id="1102795634">
  21. <name>Benefit</name>
  22. </nomenclatura>
  23. <order_nr>300</order_nr>
  24. <alt>
  25. <![CDATA[Vit support]]>
  26. </alt>
  27. <title>
  28. <![CDATA[]]>
  29. </title>
  30. <headline>
  31. <![CDATA[VITAMINS C, E]]>
  32. </headline>
  33. <filename>html/product_images/benefit_4120.png</filename>
  34. <text>
  35. <![CDATA[<p>Protect skin cells from UV damage&nbsp;</p>]]>
  36. </text>
  37. </content>
  38. </contents>
  39. <!-- analysis_table -->
  40. <ingredient-amounts type="array">
  41. <ingredient_amount>
  42. <amount type="float">0.06</amount>
  43. <unit name_key="percent" id="10">
  44. <name>%</name>
  45. </unit>
  46. <ingredient name_key="arachidonic_acid" id="3">
  47. <ingredient_section name_key="analysis_table" id="865537301">
  48. <name>Analysis</name>
  49. </ingredient_section>
  50. <name>Arachidonic acid</name>
  51. </ingredient>
  52. </ingredient_amount>
  53. <ingredient_amount>
  54. <amount type="float">0.277</amount>
  55. <unit name_key="mg_per_kg" id="30">
  56. <name>mg/kg</name>
  57. </unit>
  58. <ingredient name_key="biotin" id="58">
  59. <ingredient_section name_key="analysis_table" id="865537301">
  60. <name>Analysis</name>
  61. </ingredient_section>
  62. <name>Biotine</name>
  63. </ingredient>
  64. </ingredient_amount>
  65. <ingredient_amount>
  66. <amount type="float">0.082</amount>
  67. <unit name_key="percent" id="10">
  68. <name>%</name>
  69. </unit>
  70. <ingredient name_key="calcium" id="7">
  71. <ingredient_section name_key="analysis_table" id="865537301">
  72. <name>Analysis</name>
  73. </ingredient_section>
  74. <name>Calcium</name>
  75. </ingredient>
  76. </ingredient_amount>
  77. <ingredient_amount>
  78. <amount type="float">0.46</amount>
  79. <unit name_key="percent" id="10">
  80. <name>%</name>
  81. </unit>
  82. <ingredient name_key="chlore" id="95">
  83. <ingredient_section name_key="minerals" id="1">
  84. <name>Minerals</name>
  85. </ingredient_section>
  86. <name>Chlore</name>
  87. </ingredient>
  88. </ingredient_amount>
  89. <ingredient_amount>
  90. <amount type="float">200.0</amount>
  91. <unit name_key="mg_per_kg" id="30">
  92. <name>mg/kg</name>
  93. </unit>
  94. <ingredient name_key="choline" id="31">
  95. <ingredient_section name_key="vitamins" id="2">
  96. <name>Vit</name>
  97. </ingredient_section>
  98. <name>Choline</name>
  99. </ingredient>
  100. </ingredient_amount>
  101. <ingredient_amount>
  102. <amount type="float">1.5</amount>
  103. <unit name_key="mg_per_kg" id="30">
  104. <name>mg/kg</name>
  105. </unit>
  106. <ingredient name_key="copper" id="89">
  107. <ingredient_section name_key="minerals" id="1">
  108. <name>Minerals</name>
  109. </ingredient_section>
  110. <name>Copper</name>
  111. </ingredient>
  112. </ingredient_amount>
  113. </ingredient-amounts>
  114. </country_product>
  115. </country_products>


Czy SimpleXML to dobre wyjście w tej sytuacji?
Obawiam się tych wszystkich pętli, przy zapisie kilkuset produktów pewnie będzie ciężko. Jak inaczej mogę dotrzeć do wartości zagnieżdżonej w danym elemencie wyszukując go według atrubutu?

Z góry dziękuję za pomoc,
Pozdrawiam

Ten post edytował flipp 8.07.2013, 09:46:15
Go to the top of the page
+Quote Post
matiit
post 7.07.2013, 17:00:46
Post #2





Grupa: Zarejestrowani
Postów: 365
Pomógł: 70
Dołączył: 5.04.2009

Ostrzeżenie: (0%)
-----


Xpath.

http://php.net/manual/en/simplexmlelement.xpath.php
http://www.dimuthu.org/blog/2008/09/30/xpath-in-simplexml/

Ten post edytował matiit 7.07.2013, 17:01:26
Go to the top of the page
+Quote Post
flipp
post 9.07.2013, 23:50:06
Post #3





Grupa: Zarejestrowani
Postów: 7
Pomógł: 0
Dołączył: 30.03.2013

Ostrzeżenie: (0%)
-----


Bardzo dziękuję za wskazówkę smile.gif.

Mam jeszcze pewien problem z wyciągnięciem składników, są zapisane tak:
  1. <contents>
  2. <content type="ImageParagraphContent">
  3. <nomenclatura key="Benefit" id="1102795634">
  4. <name>Benefit</name>
  5. </nomenclatura>
  6. <order_nr>300</order_nr>
  7. <alt>
  8. <![CDATA[Vit support]]>
  9. </alt>
  10. <title>
  11. <![CDATA[]]>
  12. </title>
  13. <headline>
  14. <![CDATA[VITAMINS C, E]]>
  15. </headline>
  16. <filename>html/product_images/benefit_4120.png</filename>
  17. <text>
  18. <![CDATA[<p>Protect skin cells from UV damage </p>]]>
  19. </text>
  20. </content>
  21. </contents>


Wklepuję takie zapytanie:
  1. $queryresult = $xml->xpath("//contents/content[@type='ImageParagraphContent']/nomenclatura[@key='Benefit']");
  2. foreach($queryresult as $item){
  3. echo $item->name
  4. }


Poprawnie wyświetla mi się zawartość <name></name> "Benefit", a chcę oprócz tego wyświetlić to co jest w:
  1. <headline>
  2. <![CDATA[VITAMINS C, E]]>
  3. </headline>
  4. <filename>html/product_images/benefit_4120.png</filename>
  5. <text>
  6. <![CDATA[<p>Protect skin cells from UV damage </p>]]>
  7. </text>

Czyli nie w elemencie <nomenclatura>, ale na równi z nim.

Jak mogę sprawdzić, czy <nomenclatura> ma key='Benefit', a następnie wrócić wyżej i wyświetlić <headline> i <text>?

Pozdrawiam

Ok, odpowiedź na powyższe pytanie już mam, wystarczyło zastosować /parent::*
  1. $queryresult = $xml->xpath("//contents/content[@type='ImageParagraphContent']/nomenclatura[@key='Benefit']/parent::*");


Kolejny problem mam z wyświetleniem tabeli z:
  1. <ration_csv>Dawka;26 mg;28 mg;30 mg;32 mg;34 mg;36 mg;38 mg;40 mg;42 mg;44 mg;45 mg
  2. ;;;;;;;;;;;
  3. Zapotrzebowanie niskie;275;290;305;320;335;350;365;380;390;405;415
  4. ;;;;;;;;;;;
  5. Zapotrzebowanie normalne;310;330;345;360;380;395;410;425;440;455;465
  6. ;;;;;;;;;;;
  7. Zapotrzebowanie wysokie;345;365;385;400;420;440;455;475;490;510;515
  8. </ration_csv>


Próbowałem rozbić to najpierw na wiersze tabeli (następnie chciałem na poszczególne komórki, z tym nie byłoby problemu bo separatorem jest ';' ).
  1. <?php
  2. $table = $product->ration_csv;
  3.  
  4. $table_row = explode('\n', $table);
  5. ?>


W wyniku dostaję jednoelementową tablicę z całą zawartością <ration_csv>. Problem z rozpoznaniem przejścia do kolejnej linii, \n nie zdaje egzaminu.
Jak inaczej mogę to rozbić?




Ten post edytował flipp 8.07.2013, 10:04:39
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 27.04.2024 - 21:43