Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem ze zmianną globalną. Parsing SAX (XML)
Forum PHP.pl > Forum > PHP
mtrpoland
Witajcie,
natrafiłem na dziwną sytuację. Już wyczerpałem wszelkie pomysły na rozwiązanie.

Parsuje SAX'em plik o strukurze:
  1. <?xml version="1.0" encoding='UTF-8'?>
  2. <PictureCollection>
  3. <MainPath>ble</MainPath>
  4. <Picture>
  5. <ID></ID>
  6. <PATH></PATH>
  7. <DESC></DESC>
  8. </Picture>
  9. <Picture>
  10. <ID></ID>
  11. <PATH></PATH>
  12. <DESC></DESC>
  13. </Picture>
  14. </PictureCollection>


Potrzebuję wydobyć ścieżkę i opis obrazka o konkretnym ID.
Napisałem funkcje:
  1. // FUNKCJE SLUZACE DO WCZYTYWANIA DANYCH KONKRETNEGO OBRAZKU
  2. function dataHandler($parser, $data) {
  3. global $currentTag;
  4. global $currentPID;
  5. global $insideTargetPicture;
  6. global $picPath;
  7. global $picDesc;
  8. if(0==strcmp($currentTag,"ID"))
  9. if($data==$currentPID)
  10. $insideTargetPicture = 1;
  11. if((0==strcmp($currentTag,"PATH"))&&$insideTargetPicture)
  12. $picPath = $data;
  13. if((0==strcmp($currentTag,"DESC"))&&$insideTargetPicture)
  14. $picDesc = $data;
  15. }
  16. function startElement($parser, $name, array $attr) {
  17. global $currentTag;
  18. $currentTag = $name;
  19. }
  20. function endElement($parser, $name) {
  21. global $insideTargetPicture;
  22. if(0==strcmp($name,"PICTURE"))
  23. $insideTargetPicture = 0;
  24. }
  25.  
  26. function fillPictureData($id, &$url, &$desc) {
  27. global $currentPID;
  28. global $currentTag;
  29. global $insideTargetPicture;
  30. global $picPath;
  31. global $picDesc;
  32. $currentPID = $id;
  33. $insideTargetPicture = 0;
  34. $file = "./data/welcomePictures.xml";
  35. $parser = xml_parser_create();
  36. xml_set_element_handler($parser, "startElement", "endElement");
  37. xml_set_character_data_handler($parser, "dataHandler");
  38.  
  39. if (!($fp = fopen($file, "r")))
  40. die("could not open XML input");
  41.  
  42. while ($data = fread($fp, 4096))
  43. if(!xml_parse($parser, $data, feof($fp)))
  44. die(sprintf("XML error: %s at line %d",
  45. xml_error_string(xml_get_error_code($parser)),
  46. xml_get_current_line_number($parser)));
  47.  
  48. $url = $picPath;
  49. $desc = $picDesc;
  50. xml_parser_free($parser);
  51. }


Problem jest natury "autozerującej" się zmiennej globalnej
  1. $picPath
.
Zmienna jest ładnie wypełniana w
  1. dataHandler
w którym odczytywana jest pożądana wartość.
Jednak po zakończeniu parsowania, zmienna jest już pusta, mimo że w kodzie zmienia się tylko raz w
  1. dataHandler
.

Jakieś pomysły?
:-)
franki01
Nie myślałeś, żeby z tego zrobić klasę? Co do pytania. Spróbuj zobaczyć, czy pomoże coś używanie $GLOBALS['picPath'], zamiast tego global $picPath.
mtrpoland
Rozwiązałem problem!
Kruczkiem był fakt, że dataHandler może być wywoływany kilkukrotnie w trakcie parsowania wewnątrz tego samego znacznika! Tak jest napisane w dokumentacji php5.
Ja w konstrukcji kodu założyłem, że tylko raz co powodowało błędy.

Poprawny kod poniżej:
  1. <?php
  2. // klasa służąca do wydobycia z pliku xml informacji o wybranym zdjeciu
  3. // wejście: numer zdjecia
  4. // wyjscie: ścieżka dostępowa
  5. // opis zdjęcia
  6. class PictureParser {
  7. private $m_path=""; // ścieżka żądanego obrazka
  8. private $m_desc=""; // opis żądanego obrazka
  9. private $m_height=""; // wysokość żądanego obrazka
  10. private $m_width=""; // szerokość żądanego obrazka
  11. private $m_id; // ID żądanych danych
  12. private $m_xmlFile; // Ścieżka do pliku XML
  13.  
  14. private $m_insidePicture = 0; // 1 gdy parser znajduje się w środku znacznika <Picture>
  15. private $m_insideTargetPicture = 0; // 1 gdy jestesmy w srodku <Picture> o żądanym ID!
  16. private $m_currentTag = ""; // aktualnie przetwarzany tag
  17. private $m_prevTag= ""; // poprzednio przetwarzany tag
  18. // jest on potrzebny ponieważ metoda dataHandler może
  19. // być wywoływana kilkukrotnie wewnątrz jednego znacznika
  20. function __construct($id, $xml) {
  21. $this->m_id = $id;
  22. $this->m_xmlFile = $xml;
  23. }
  24. // metody parsera
  25. // Uwaga Metoda dataHandler może być wywoływana kilkukrotnie wewnątrz jednego znacznika
  26. private function dataHandler($parser, $data) {
  27. if($this->m_insidePicture==0) return;
  28. if(0==strcmp($this->m_currentTag,"ID"))
  29. if($data==$this->m_id)
  30. $this->m_insideTargetPicture = 1;
  31. if((0==strcmp($this->m_currentTag,"PATH"))&&$this->m_insideTargetPicture)
  32. $this->m_path .= $data;
  33. if((0==strcmp($this->m_currentTag,"DESC"))&&$this->m_insideTargetPicture)
  34. $this->m_desc .= $data;
  35. if((0==strcmp($this->m_currentTag,"HEIGHT"))&&$this->m_insideTargetPicture)
  36. $this->m_height .= $data;
  37. if((0==strcmp($this->m_currentTag,"WIDTH"))&&$this->m_insideTargetPicture)
  38. $this->m_width .= $data;
  39. /*
  40.   echo "m_insidePicture: ".$this->m_insidePicture."<br/>";
  41.   echo "m_insideTargetPicture: ".$this->m_insideTargetPicture."<br/>";
  42.   echo "m_currentTag: ".$this->m_currentTag."<br/>";
  43.   echo "DATA: ".$data."<br/>";
  44.   echo "m_path: ".$this->m_path."<br/>";
  45.   echo "------------------<br/>";
  46. */
  47. }
  48. private function startElement($parser, $name, array $attr) {
  49. $this->m_currentTag = $name;
  50. if(!strcmp($name,"PICTURE"))
  51. $this->m_insidePicture = 1;
  52. }
  53. private function endElement($parser, $name) {
  54. if(!strcmp($name,"PICTURE")) {
  55. $this->m_insidePicture = 0;
  56. $this->m_insideTargetPicture = 0;
  57. }
  58. }
  59.  
  60.  
  61. // parsowanie
  62. public function parse() {
  63. $parser = xml_parser_create();
  64. xml_set_element_handler($parser, array("PictureParser","startElement"), array("PictureParser","endElement"));
  65. xml_set_character_data_handler($parser, array("PictureParser","dataHandler"));
  66.  
  67. $fp = fopen($this->m_xmlFile, "r") or die("could not open XML input");
  68.  
  69. while($data = fread($fp, 4096))
  70. xml_parse($parser, $data, feof($fp))
  71. or
  72. die(sprintf("XML error: %s at line %d",
  73. xml_error_string(xml_get_error_code($parser)),
  74. xml_get_current_line_number($parser)));
  75. xml_parser_free($parser);
  76. }
  77.  
  78. // metody uzyskujące wyniki parsowania
  79. public function getPath() {
  80. return $this->m_path;
  81. }
  82. public function getDesc() {
  83. return $this->m_desc;
  84. }
  85. public function getHeight() {
  86. return $this->m_height;
  87. }
  88. public function getWidth() {
  89. return $this->m_width;
  90. }
  91.  
  92. }
  93. ?>
  94.  
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.