Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Przedszkole _ [PHP] Odczyt XML

Napisany przez: Puchatek 4.07.2019, 12:02:46

Dzień dobry, mam pewien problem dotyczący odczytu pliku XML.
Posiadam poniższą strukturę (urywek kodu) - standard ceneo.

  1. <offers>
  2. <o id="47" url="url" price="24.47" stock="32" weight="0.027">
  3. <cat><![CDATA[Kategoria]]></cat>
  4. <name><![CDATA[Nazwa]]></name>
  5. <imgs>
  6. <main url="link"/>
  7. <i url="link"/>
  8. </imgs>
  9. <desc><![CDATA[OPIS]]></desc>
  10. <attrs>
  11. <a name="Producent"><![CDATA[Producent]]></a>
  12. <a name="Kod_Producenta"><![CDATA[Kod]]></a>
  13. <a name="EAN"><![CDATA[0000000000000]]></a>
  14. </attrs>
  15. </o>
  16. </offers>


Moim zamiarem jest przeszukanie całego pliku XML - wyszukanie w nim odpowiedniego numeru EAN a następnie pobranie ceny produktu, który ma ten EAN przypisany.
Oto częśc mojego kodu:
  1. $oFile = http://www.php.net/file_get_contents('Adres do XML');
  2. $oSimpleXmlObject = new SimpleXmlElement($oFile);
  3. $oImageSection = $oSimpleXmlObject->xpath('/o/attrs/a["name"]=EAN[.='.$ZmiennaEAN.']/parent::*');
  4. foreach($oImageSection[0]->o['price'] as $oImage)
  5. {
  6. }


Chodzi mi dokładniej o pomoc w zapisaniu ścieżki. Nie mam problemu kiedy każdy parametr jest w osobnym znaczniku. Natomiast tutaj w jednym znaczniku <a> jest name="Producent", name="Kod_Producenta", name="EAN". W jaki sposób to zapisać?

Napisany przez: SmokAnalog 4.07.2019, 12:54:39

Nie jestem ekspertem w XPath, ale takie coś działa:

Kod
//o[descendant::attrs/a[@name='Producent' and text()='abc']][descendant::attrs/a[@name='Kod_Producenta' and text()='abc']][descendant::attrs/a[@name='EAN' and text()='abc']]


Być może można to uprościć. Działa jeśli oczywiście wstawisz coś własnego pod "abc".

Napisany przez: Puchatek 4.07.2019, 13:52:40

Zastosowałem taki zapis:

  1. $oImageSection = $oSimpleXmlObject->xpath("/o[descendant::attrs/a[@name='EAN' and text()=".$ZmiennaEAN."]]/parent::*");
  2. foreach($oImageSection[0]->o[@price] as $oImage)

Niestety również nie działa.

Napisany przez: trueblue 4.07.2019, 14:05:58

Kod
'//o/attrs/a[@name="EAN"][contains(text(),' . $ZmiennaEAN . ')]/../..'


Polecam:
https://kawalekkodu.pl/the-tag-is-out-there-czyli-domxpath-s01e01
https://kawalekkodu.pl/the-tag-is-out-there-czyli-domxpath-s01e02
https://kawalekkodu.pl/the-tag-is-out-there-czyli-domxpath-s01e03
https://kawalekkodu.pl/the-tag-is-out-there-czyli-domxpath-s01e04

Napisany przez: Puchatek 4.07.2019, 15:05:49

Dziękuję za pomoc, wygląda na to, że jest ok, natomiast pozostaje jeszcze pętla foreach, w której pobierana jest cena.
Spróbowałem na 2 sposoby.
1.

  1. $oImageSection = $oSimpleXmlObject->xpath('//o/attrs/a[@name="EAN"][contains(text(),' . $ZmiennaEAN . ')]/../..');
  2. foreach($oImageSection[0]->o[@price] as $oImage)


2.
  1. $oImageSection = $oSimpleXmlObject->xpath('//o/attrs/a[@name="EAN"][contains(text(),' . $ZmiennaEAN . ')]/../../o[@price]');
  2. foreach($oImageSection[0] as $oImage)


Żaden z powyższych sposobów nie pobiera potrzebnych danych.

Napisany przez: Neutral 4.07.2019, 15:10:52

Napisz, co zwraca $oImageSection.

Napisany przez: trueblue 4.07.2019, 17:48:36

  1. $dom = new DOMDocument;
  2. $dom->encoding = 'UTF-8';
  3. $dom->loadXML('tu_xml');
  4.  
  5. $ZmiennaEAN = '0000000000000';
  6.  
  7. $xpath = new DOMXPath($dom);
  8. $offers = $xpath->query('//o/attrs/a[@name="EAN"][contains(text(),'.$ZmiennaEAN.')]/../..');
  9.  
  10. foreach($offers as $offer) {
  11. http://www.php.net/echo $offer->getAttribute('price');
  12. }

Napisany przez: Puchatek 8.07.2019, 11:40:04

Po zastosowaniu w/w sposobu otrzymuję takie komunikaty.
Przeszukiwałem internet w celu rozwiązania tego problemu, jednak nic nie pomaga.

Kod
Warning: DOMDocument::loadXML(): Start tag expected, '<' not found in Entity, line: 1 in ...
Warning: DOMDocument::loadXML(): Start tag expected, '<' not found in Entity, line: 1 in ...

Warning: DOMDocument::loadXML(): Start tag expected, '<' not found in Entity, line: 1 in ...

Warning: DOMDocument::loadXML(): Start tag expected, '<' not found in Entity, line: 1 in ...

Napisany przez: Tomplus 8.07.2019, 12:41:50

Spróbuj:

  1. $dom->load('tu_xml');

Napisany przez: Puchatek 8.07.2019, 15:01:30

Niestety, ale nadal całość nie funkcjonuje.
Nie zostaje wyświetlona żadna wartość.

  1. $dom = new DOMDocument;
  2. $dom->encoding = 'UTF-8';
  3. $dom->load('link');
  4. $xpath = new DOMXPath($dom);
  5. $offers = $xpath->query('//o/attrs/a[@name="EAN"][contains(text(),'.$ZmiennaEAN.')]/../..');
  6. foreach($offers as $offer) {
  7. http://www.php.net/echo $offer->getAttribute('price');
  8. }

Napisany przez: viking 8.07.2019, 16:07:05

A wartość tekstową atrybutu name z cdata dostajesz? Pamiętam że coś trzeba było włączyć do parsowania.

Napisany przez: Neutral 8.07.2019, 16:24:04

https://www.lonhosford.com/lonblog/2011/01/07/php-simplexml-load-xml-file-preserve-cdata-remove-whitespace-between-nodes-and-return-json/ https://www.php.net/manual/en/class.domdocument.php

Chyba chodzi o

Cytat
public bool $preserveWhiteSpace = TRUE ;
, ale nie jestem pewien.

@Puchatek, zapisz plik z kodowaniem UTF-8 z BOM i sprawdź, czy pójdzie. Jeśli, nie to zapisz ten plik z kodowaniem UTF-8 bez BOM. Popróbuj tak z dwoma plikami, tym "index.php" i tym "index.xml".

BOM - Byte Order Mark.

Napisany przez: Puchatek 10.07.2019, 08:16:54

Zmiany w kodowaniach również nie pomogły.
Chyba odpuszczam temat z wykorzystaniem tego XMLa, mam jeszcze możliwość pobierania tych samych danych z API tylko muszę poszerzyć swoją wiedzę na ten temat.
Dziękuję bardzo za pomoc.

Napisany przez: trueblue 10.07.2019, 08:23:42

A może pokażesz ten XML? Czy dostarczasz poprawną strukturę dla metody load?

Napisany przez: Puchatek 11.07.2019, 14:30:14

Struktura wygląda tak. Całego pliku XML nie mogę udostępnić ze względu na umowę.

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <offers xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
  3. <o id="96727" url="url" price="56.83" stock="1511" weight="0.42">
  4. <cat><![CDATA[kategoria1]]></cat>
  5. <name><![CDATA[nazwa1]]></name>
  6. <imgs>
  7. <main url="url"/>
  8. <i url="url"/>
  9. <i url="url"/>
  10. <i url="url"/>
  11. <i url="url"/>
  12. <i url="url"/>
  13. <i url="url"/>
  14. <i url="url"/>
  15. <i url="url"/>
  16. </imgs>
  17. <desc><![CDATA[opis]]></desc>
  18. <attrs>
  19. <a name="Producent"><![CDATA[producent]]></a>
  20. <a name="Kod_Producenta"><![CDATA[1111111]]></a>
  21. <a name="EAN"><![CDATA[1111111111111]]></a>
  22. </attrs>
  23. </o>
  24. <o id="92385" url="url" price="74.59" stock="2926" weight="2.8">
  25. <cat><![CDATA[kategoria2]]></cat>
  26. <name><![CDATA[nazwa2]]></name>
  27. <imgs>
  28. <main url="url"/>
  29. <i url="url"/>
  30. <i url="url"/>
  31. <i url="url"/>
  32. <i url="url"/>
  33. <i url="url"/>
  34. <i url="url"/>
  35. <i url="url"/>
  36. <i url="url"/>
  37. <i url="url"/>
  38. <i url="url"/>
  39. <i url="url"/>
  40. </imgs>
  41. <desc><![CDATA[opis]]></desc>
  42. <attrs>
  43. <a name="Producent"><![CDATA[producent]]></a>
  44. <a name="Kod_Producenta"><![CDATA[0000000]]></a>
  45. <a name="EAN"><![CDATA[2222222222222]]></a>
  46. </attrs>
  47. </o>
  48. </offers>

Napisany przez: trueblue 11.07.2019, 14:49:16

Brakuje cudzysłowów. Query będzie mieć taką postać:

  1. $offers = $xpath->query('//o/attrs/a[@name="EAN"][contains(text(),"' . $ZmiennaEAN . '")]/../..');

Napisany przez: Puchatek 11.07.2019, 15:09:50

Udało się, cudzysłów pomógł, serdecznie dziękuję wszystkim za pomoc smile.gif

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)