Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Poruszanie sie po strukturze XML
Forum PHP.pl > Forum > PHP
Indeo
Pewnie dla wiekszości z was zagadnienie banalne ale potrzebuję pomocy smile.gif

Chce załadować dane XML do jakiejś tablicy czy obiektu tak abym mógł się po niej poruszać na zasadzie
  1. <?php
  2. $tablica['element']['potomny_01']['potomny_02']...
  3. albo
  4. $tablica->element->potomny_01->potomny_02
  5. ?>

bo zwykłe wpakowanie danych przez xml_parse_into_struct zwraca strukturalnie słaby materiał smile.gif


Moja intencją jest po prostu wydobycie danej gałęzi i przeniesienie w inne miejsce.

Dzięki za pomoc smile.gif
Cysiaczek
Nic prostszego - simpleXML - tworzy swój obiekt i pozwala nawigować jak Ci się żywnie podoba.

Pozdrawiam.
Indeo
Podoba mi sie to ale martwi mnie jedna rzecz. Prosze zobaczyć co dzieje się z tagami pliku worda:

Oryginalny XML worda zawiera:
  1. <w:sectPr >
  2.      <w:pgSz w:w="11906" w:h="16838" ></w:pgSz>
  3.      <w:pgMar w:top="1417" w:right="1417" w:bottom="1417" w:left="1417" w:header="708" w:footer="708" w:gutter="0" ></w:pgMar>
  4.      <w:cols w:space="708" ></w:cols>
  5.      <w:docGrid w:line-pitch="360" ></w:docGrid>
  6. </w:sectPr>


natomiast po przechwyceniu XML'a przez SimpleXML wygląda to tak:
  1. <sectPr>
  2.      <pgSz w="11906" h="16838"/>
  3.      <pgMar top="1417" right="1417" bottom="1417" left="1417" header="708" footer="708" gutter="0"/>
  4.      <cols space="708"/>
  5.      <docGrid line-pitch="360"/>
  6. </sectPr>


To że z pustych tagów zrobił tagi pojedyncze to spoko, ale poginęły nazwy elementów worda - znikneło wyrażenie "w:" , które jednak dla worda jest istotne.
I czemu tak się dzieje?
nospor
simpleXML nie rozpoznaje namespaców (u ciebie to wlasnie w:).
Poszukaj jakiejs klasy opartej na DOM, moze one bedą to respektowaly, gdyz sam DOM rozpoznaje namespacy. Wiem, gdyz sam niedawno przenioslem sie na DOM spowodow wlasnie namespacow
Indeo
Ot i szok. Nie wiedziałem co to namespaces, a napisałem program rozwalający całą strukturę pliku XML'owego worda z 3 linijkowego krzaczora w piękna drzewiastą strukturę za pomoca samego xml_parse_into_struct i po powrotnym zrzuceniu wszystkiego z tabelki wciąż się otwiera w wordzie smile.gif!

Jak usłyszałem DOM aż mi ciary przeszły ... naprawde nie ma nic prostszego? Przecież na boga to tylko pliki tekstowe ze znacznikami ...
nospor
Cytat
Jak usłyszałem DOM aż mi ciary przeszły ... naprawde nie ma nic prostszego?

DOM nie jest taki zly winksmiley.jpg

Ale jak mowilem, przejrzyj klasy, chociazby na phpclasses.org, ktore wykorzystują DOM. Zapewne są przyjemniejsze w uzyciu a i moze namespacy zachowują.
Wynikami podziel sie w tym topicu bo sam jestem ciekaw.
Indeo
Już szukam. Dam znać smile.gif

Muszę przyznać, że jestem troche zawiedziony całym zamieszaniem wokół XML, a raczej odczuciem chaosu spowodowanym brakiem (jak dla mnie) przejrzystych ścieżek poznania aparatu jego obsługi. rzeczywiście znalazłem wiele klas opartych na DOM XML, ale za kazdym razem i tak trzeba było ingerować w logikę DOM więc bez znajomości DOm XML taka klasa mi sie nie przyda. Czytanie o DOM XML na php.net przypomina mi tą reklamę z " .... ntfs z jakims lewarowaniem" na co klient wybałusza gały ... :/ Po prostu o ile sam XML jest strukturalnie poukładany o tyle na ironię dokumentacja o narzędziach do niego jest chaotyczna.

Reasumując. Przejrzałem na php.net przykłady oparte na klasycznych funkcjach XML'owych php, i po drobnych modyfikacjach mam to czego chciałem. Mam dwie klasy - jedna odpowiada za odwzorowanie wyrażenia xml na hierarchiczną tablicę i drugą o działaniu odwrotnym tak żeby zmodyfikowaną tablice można było z powrotem zapisac jako XML.

Nie znam się specjalnie na XML. Testowałem je na plikach worda zapisanych w formacie XML i działają.


Poniżej klasy:
xml do tablicy
  1. <?php
  2. /*
  3. Klasa przetwarzająca wyrażenie XML na tablicę z zachowanie hierarchii, atrybutów
     i namespace's (przynajmniej tam gdzie używałem - xml worda)
  4. Znalazłem to na php.net, dodałem tylko opcje zachowania wielkości liter
  5. Klasa korzysta ze standardowych funkcji pbsługi XML więc nie potrzeba DOM XML it
    p.
  6.  
  7.  
  8. $objXML = new xml2Array();
  9. $arrOutput = $objXML->parse($strYourXML);
  10. print_r($arrOutput);
  11. */
  12.  
  13. class xml2Array {
  14.  var $arrOutput = array();
  15.  var $resParser;
  16.  var $strXmlData;
  17.  
  18. function parse($strInputXML) {
  19. $this->resParser = xml_parser_create ();
  20. xml_parser_set_option($this->resParser , XML_OPTION_CASE_FOLDING, 0);
  21. //xml_parser_set_option($this->resParser , XML_OPTION_SKIP_WHITE, 1);
  22. xml_set_object($this->resParser,$this);
  23. xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");
  24.  
  25. xml_set_character_data_handler($this->resParser, "tagData");
  26. $this->strXmlData = xml_parse($this->resParser,$strInputXML );
  27. if(!$this->strXmlData) {
  28. die(sprintf("XML error: %s at line %d",
  29. xml_error_string(xml_get_error_code($this->resParser)),
  30. xml_get_current_line_number($this->resParser)));
  31. }
  32. xml_parser_free($this->resParser);
  33. return $this->arrOutput;
  34. }
  35.  
  36. function tagOpen($parser, $name, $attrs) {
  37. $tag=array("name"=>$name,"attrs"=>$attrs); 
  38. array_push($this->arrOutput,$tag);
  39. }
  40.  
  41. function tagData($parser, $tagData) {
  42. if(trim($tagData)) {
  43. if(isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) {
  44. $this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $tagData;
  45. }else {
  46. $this->arrOutput[count($this->arrOutput)-1]['tagData'] = $tagData;
  47. }
  48. }
  49. }
  50.  
  51. function tagClosed($parser, $name) {
  52. $this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this->arrOutput)-1];
  53. array_pop($this->arrOutput);
  54. }
  55. }
  56. ?>



z tablicy do XML:

  1. <?php
  2. /*
  3. Klasa o działaniu odwrotnym do xml2Array przetwarzająca tablicę na wyrażenie XML
     z zachowanie hierarchii, atrybutów i namespace's (przynajmniej tam gdzie używałem - xml worda)
  4. Znalazłem to na php.net, ale był problem z wartościami tagów (gineły) więc trochę kod rozwinąłem
  5. Klasa korzysta ze standardowych funkcji pbsługi XML więc nie potrzeba DOM XML it
    p.
  6.  
  7.  
  8. $objXML = new Array2xml();
  9. $xmlOutput = $objXML->parse($array);//$array[0] jeśli tablica jest zwrócona przez klasę xml2Array :)
  10. print_r($xmlOutput);
  11. */
  12. class Array2xml{
  13.  
  14. function parse($root){
  15. if(count($root) > 0){
  16. $curr_name = $root['name'];
  17. $attribs = $root['attrs'];
  18. $curr_childs = $root['children'];
  19. $curr_data = $root['cdata'];
  20. $curr_tagdata=$root['tagData'];
  21. $xml .= '<'.$curr_name;
  22.  
  23. if(count($attribs) > 0){
  24. $i = 1;
  25. foreach($attribs as $key => $value){
  26. $curr_attribs .= $key.'="'.$value.'"';
  27. $i++;
  28. if($i <= count($attribs)){
  29. $curr_attribs .= ' ';
  30. }
  31. }
  32. $xml .= ' '.$curr_attribs;
  33. }
  34.  
  35. if($curr_data != ''){
  36. $xml .= '><![CDATA['.$curr_data.']]></'.$curr_name.'>';
  37. }else {
  38. if(count($curr_childs) > 0){
  39. $xml .= '>';
  40. if($curr_tagdata) $xml.=$curr_tagdata;
  41.  foreach($curr_childs as $child){
  42. $xml .= $this->parse($child);
  43. }
  44. $xml .= '</'.$curr_name.'>';
  45.  } else {
  46.  if($curr_tagdata){
  47.  $xml.='>';
  48.  $xml.=$curr_tagdata;
  49.  $xml .= '</'.$curr_name.'>';
  50. }else{
  51. $xml .= '/>';
  52. }
  53. }
  54.  }
  55.  } 
  56.  return $xml;
  57.  }
  58.  
  59.  }
  60. ?>



Mając takie wyrażenie XML:
  1. <root xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" >
  2.      <w:ocean >spokojny
  3.            <morze >czerwone</morze>
  4.            <morze >czarne</morze>
  5.      </w:ocean>
  6.      <kontynent >
  7.            <o:kraj >Polska</o:kraj>
  8.      </kontynent>
  9. </root>


dostajemy taką tablicę:

  1. Array
  2. (
  3. [0] => Array
  4. (
  5. [name] => root
  6. [attrs] => Array
  7. (
  8. )
  9.  
  10. [children] => Array
  11. (
  12. [0] => Array
  13. (
  14. [name] => w:ocean
  15. [attrs] => Array
  16. (
  17. )
  18.  
  19. [tagData] => spokojny
  20. [children] => Array
  21. (
  22. [0] => Array
  23. (
  24. [name] => morze
  25. [attrs] => Array
  26. (
  27. )
  28.  
  29. [tagData] => czerwone
  30. )
  31.  
  32. [1] => Array
  33. (
  34. [name] => morze
  35. [attrs] => Array
  36. (
  37. )
  38.  
  39. [tagData] => czarne
  40. )
  41.  
  42. )
  43.  
  44. )
  45.  
  46. [1] => Array
  47. (
  48. [name] => kontynent
  49. [attrs] => Array
  50. (
  51. )
  52.  
  53. [children] => Array
  54. (
  55. [0] => Array
  56. (
  57. [name] => o:kraj
  58. [attrs] => Array
  59. (
  60. )
  61.  
  62. [tagData] => Polska
  63. )
  64.  
  65. )
  66.  
  67. )
  68.  
  69. )
  70.  
  71. )
  72.  
  73. )
thornag
Fajne, tylko dlaczego az dwie klasy ? Mozna to zawrzec w jednej paczce i bedzie wygodniej.
Indeo
Oczywiście, tak jakoś wyszło smile.gif Własnie użyłem tych klas do załadowania do tablicy dokumentu worda w formacie XML z załączonym zdjęciem, a potem z powrotem zrzuciłem wszystko do pliku xml i działa smile.gif.
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.