Parsing af XML. Springer varer over, du ikke har brug for

Parsing af XML betyder i bund og grund at krydse et XML-dokument og returnere de relevante data. Mens et stigende antal webtjenester returnerer data i JSON-format, bruger de fleste stadig XML, så det er vigtigt at mestre XML-parsing, hvis du vil bruge hele rækken af ​​tilgængelige API'er.

Brug af udvidelsen SimpleXML i PHP, som blev tilføjet i PHP 5.0, er arbejdet med XML meget nemt og ligetil. I denne artikel vil jeg vise dig, hvordan du gør dette.

Grundlæggende brug

Lad os starte med følgende eksempel sprog.xml:


>

> 1972>
> Dennis ritchie >
>

> 1995>
> Rasmus Lerdorf >
>

> 1995>
> James gæsling >
>
>

Dette XML-dokument indeholder en liste over programmeringssprog med nogle oplysninger om hvert sprog: året for dets implementering og navnet på dets skaber.

Det første trin er at indlæse XML ved hjælp af funktioner enten simplexml_load_file () eller simplexml_load_string ()... Som navnet på funktionerne antyder, vil førstnævnte indlæse XML fra en fil, og sidstnævnte vil indlæse XML fra en streng.

Begge funktioner læser hele DOM-træet ind i hukommelsen og returnerer et objekt SimpleXMLElement... I ovenstående eksempel er objektet gemt i $ languages-variablen. Du kan bruge funktioner var_dump () eller print_r () for at få detaljer om det returnerede objekt, hvis du vil.

SimpleXMLElement-objekt
[lang] => Array
[0] => SimpleXMLElement-objekt
[@ attributter] => Array
[navn] => C
[dukkede op] => 1972
[skaber] => Dennis Ritchie
[1] => SimpleXMLElement-objekt
[@ attributter] => Array
[navn] => PHP
[dukkede op] => 1995
[skaber] => Rasmus Lerdorf
[2] => SimpleXMLElement-objekt
[@ attributter] => Array
[navn] => Java
[dukkede op] => 1995
[skaber] => James Gosling
)
)

Denne XML indeholder rodelementet Sprog, hvori der er tre elementer lang. Hvert element i arrayet svarer til et element lang i XML-dokumentet.

Du kan få adgang til egenskaberne for et objekt ved hjælp af operatoren -> ... For eksempel vil $ languages-> lang returnere dig et SimpleXMLElement-objekt, der matcher det første element lang... Dette objekt indeholder to egenskaber: dukkede op og skaberen.

$ sprog -> lang [0] -> dukkede op;
$ sprog -> lang [0] -> skaber;

Det er meget nemt at vise en liste over sprog og vise deres egenskaber ved hjælp af en standardløkke som f.eks for hver.

foreach ($ sprog -> lang som $ lang) (
printf (
"" ,
$ lang ["navn"],
$ lang -> dukkede op,
$ lang -> skaber
) ;
}

Bemærk, hvordan jeg fik adgang til attributnavnet på lang-elementet for at få sprognavnet. På denne måde kan du få adgang til enhver attribut for et element repræsenteret som et SimpleXMLElement-objekt.

Arbejde med navnerum

Når du arbejder med forskellige webtjenesters XML, vil du støde på elementnavneområder mere end én gang. Lad os ændre vores sprog.xml for at vise et eksempel på brug af navneområdet:



xmlns: dc =>

> 1972>
> Dennis ritchie >
>

> 1995>
> Rasmus Lerdorf >
>

> 1995>
> James gæsling >
>
>

Nu elementet skaber placeret i navnerummet dc som peger på http://purl.org/dc/elements/1.1/. Hvis du prøver at udskrive sprogskaberne ved hjælp af vores tidligere kode, så virker det ikke. For at læse elementernes navneområder skal du bruge en af ​​følgende fremgangsmåder.

Den første tilgang er at bruge URI'er direkte i kode, når der refereres til elementets navneområde. Følgende eksempel viser, hvordan dette gøres:

$ dc = $ sprog -> lang [1] -> børn ( "http://purl.org/dc/elements/1.1/") ;
echo $ dc -> skaber;

Metode børn () tager et navneområde og returnerer underordnede elementer, der starter med et præfiks. Det kræver to argumenter, det første er et XML-navneområde og det andet valgfrie argument, som er standard falsk... Hvis det andet argument er TRUE, vil navneområdet blive behandlet som et præfiks. Hvis FALSE, så vil navneområdet blive behandlet som et URL-navneområde.

Den anden tilgang er at læse URI-navnene fra dokumentet og bruge dem, når der refereres til elementnavneområdet. Dette er faktisk den bedste måde at få adgang til elementerne, fordi du ikke behøver at hardkode URI'en.

$ namespaces = $ sprog -> getNamespaces (true);
$ dc = $ sprog -> lang [1] -> børn ($ navneområder ["dc"]);

echo $ dc -> skaber;

Metode GetNamespaces () returnerer en række præfiksnavne og deres tilknyttede URI'er. Det kræver en ekstra parameter, som som standard er falsk... Hvis du indstiller det som rigtigt så vil denne metode returnere de navne, der bruges i overordnede og underordnede noder. Ellers finder den navnerum, der kun bruges i den overordnede node.

Du kan nu gå gennem listen over sprog som følger:

$ languages ​​= simplexml_load_file ("languages.xml");
$ ns = $ sprog -> getNamespaces (true);

foreach ($ sprog -> lang som $ lang) (
$ dc = $ lang -> børn ($ ns ["dc"]);
printf (
"

% s dukkede op i % d og blev oprettet af % s.

" ,
$ lang ["navn"],
$ lang -> dukkede op,
$ dc -> skaber
) ;
}

Casestudie - Parsing af en YouTube-videokanal

Lad os tage et kig på et eksempel, der modtager et RSS-feed fra en YouTube-kanal og viser links til alle videoer fra den. For at gøre dette skal du kontakte følgende adresse:

http://gdata.youtube.com/feeds/api/users/xxx/uploads

URL'en returnerer en liste over de seneste videoer fra den givne kanal i XML-format. Vi analyserer XML og får følgende oplysninger for hver video:

  • Link til video
  • Miniature
  • Navn

Vi starter med at finde og indlæse XML:

$ channel = "Kanalnavn";
$ url = "http://gdata.youtube.com/feeds/api/users/"... $ kanal. "/ uploader";
$ xml = file_get_contents ($ url);

$ feed = simplexml_load_string ($ xml);
$ ns = $ feed -> getNameSpaces (true);

Hvis du ser på XML-feedet, kan du se, at der er flere elementer derinde enhed, som hver især gemmer detaljerede oplysninger om en bestemt video fra en kanal. Men vi bruger kun thumbnails, video-url og titel. Disse tre elementer er efterkommere af elementet gruppe som til gengæld er et barn af indgang:

>

>



Titel... >

>

>

Vi vil bare gennemgå alle elementerne. indgang, og for hver af dem udtrækker vi de nødvendige oplysninger. Noter det spiller, thumbnail og titel er i medienavnerummet. Derfor skal vi fortsætte som i det foregående eksempel. Vi henter navnene fra dokumentet og bruger navnerummet, når vi refererer til elementerne.

foreach ($ feed -> entry as $ entry) (
$ gruppe = $ indgang -> børn ($ ns ["medie"]);
$ gruppe = $ gruppe -> gruppe;
$ thumbnail_attrs = $ gruppe -> thumbnail [1] -> attributter ();
$ image = $ thumbnail_attrs ["url"];
$ player = $ gruppe -> spiller -> attributter ();
$ link = $ player ["url"];
$ titel = $ gruppe -> titel;
printf ( "

" ,
$ player, $ image, $ title);
}

Konklusion

Nu hvor du ved, hvordan du bruger SimpleXML til parsing af XML-data kan du forbedre dine færdigheder ved at parse forskellige XML-feeds med forskellige API'er. Men det er vigtigt at huske på, at SimpleXML læser hele DOM ind i hukommelsen, så hvis du parser et stort datasæt, kan du løbe tør for hukommelse. Læs dokumentationen for at lære mere om SimpleXML.


Hvis du har spørgsmål, anbefaler vi at bruge vores

Nu skal vi studere arbejdet med XML. XML er et format til udveksling af data mellem websteder. Det minder meget om HTML, bortset fra at XML tillader sine egne tags og attributter.

Hvorfor har du brug for XML, når du analyserer? Nogle gange sker det sådan, at det websted, du skal parse, har en API, som du kan få det, du vil have, uden for meget belastning. Derfor lige et tip - før du analyserer siden, så tjek om den har en API.

Hvad er en API? Dette er et sæt funktioner, som du kan bruge til at sende en anmodning til dette websted og modtage det ønskede svar. Dette svar kommer oftest i XML-format. Så lad os gå i gang med at studere det.

Arbejde med XML i PHP

Antag, at du har XML. Det kan være i en streng eller gemt i en fil eller returneres efter anmodning til en bestemt URL.

Lad XML gemmes i en streng. I dette tilfælde skal du fra denne linje oprette et objekt ved hjælp af nyt SimpleXMLElement:

$ str = " Kolya 25 1000 "; $ xml = nyt SimpleXMLElement ($ str);

Nu har vi en variabel $ xml et objekt med parset XML er gemt. Ved at få adgang til egenskaberne for dette objekt, kan du få adgang til indholdet af XML-tags. Hvordan præcist - vi analyserer lidt nedenfor.

Hvis XML er gemt i en fil eller returneres ved at tilgå en URL (hvilket oftest er tilfældet), så skal du bruge funktionen simplexml_load_fil som gør det samme objekt $ xml:

Kolya 25 1000

$ xml = simplexml_load_file (sti til fil eller url);

Hvordan man arbejder

I eksemplerne nedenfor er vores XML gemt i en fil eller URL.

Lad følgende XML blive givet:

Kolya 25 1000

Lad os få navn, alder og løn på medarbejderen:

$ xml = simplexml_load_file (sti til fil eller url); echo $ xml-> navn; // udskriver "Kolya" echo $ xml-> age; // udskriver 25 echo $ xml-> løn; // vil udskrive 1000

Som du kan se, har $ xml-objektet egenskaber, der svarer til tags.

Du har måske bemærket, at mærket står ikke nogen steder i adressen. Det er fordi det er root-tagget. Du kan omdøbe den for eksempel til - og intet vil ændre sig:

Kolya 25 1000

$ xml = simplexml_load_file (sti til fil eller url); echo $ xml-> navn; // udskriver "Kolya" echo $ xml-> age; // udskriver 25 echo $ xml-> løn; // vil udskrive 1000

Der kan kun være ét root-tag i XML, ligesom et tag i normal HTML.

Lad os ændre vores XML lidt:

Kolya 25 1000

I dette tilfælde vil vi få en kæde af opkald:

$ xml = simplexml_load_file (sti til fil eller url); echo $ xml-> arbejder-> navn; // udskriver "Kolya" echo $ xml-> worker-> age; // udskriver 25 echo $ xml-> arbejder-> løn; // vil udskrive 1000

Arbejde med attributter

Lad nogle data gemmes i attributter:

Nummer 1

$ xml = simplexml_load_file (sti til fil eller url); echo $ xml-> worker ["navn"]; // viser "Kolya" echo $ xml-> worker ["age"]; // udskriver 25 echo $ xml-> arbejder ["løn"]; // udskriver 1000 echo $ xml-> worker; // viser "Nummer 1"

Bindestreg tags

Tags (og attributter) med en bindestreg er tilladt i XML. I dette tilfælde tilgås sådanne tags som dette:

Kolya Ivanov

$ xml = simplexml_load_file (sti til fil eller url); echo $ xml-> worker -> (fornavn); // udskriver "Kolya" echo $ xml-> worker -> (efternavn); // viser "Ivanov"

Iteration over en løkke

Lad nu vi ikke have én medarbejder, men flere. I dette tilfælde kan vi iterere over vores objekt ved hjælp af en foreach loop:

Kolya 25 1000 Vasya 26 2000 Peter 27 3000

$ xml = simplexml_load_file (sti til fil eller url); foreach ($ xml som $ worker) (ekko $ worker-> name; // udskriver "Kolya", "Vasya", "Petya")

Fra objekt til normal array

Hvis du ikke er tryg ved at arbejde med et objekt, kan du konvertere det til et normalt PHP-array ved at bruge følgende smarte trick:

$ xml = simplexml_load_file (sti til fil eller url); var_dump (json_decode (json_encode ($ xml), sand));

Mere information

Parsing baseret på sitemap.xml

Ofte har webstedet en sitemap.xml-fil. Denne fil gemmer links til alle sider på webstedet for at gøre det nemmere at indeksere dem af søgemaskiner (indeksering er faktisk parsing af webstedet af Yandex og Google).

Generelt bør vi ikke bekymre os meget om, hvorfor denne fil er nødvendig, det vigtigste er, at hvis den findes, kan du ikke klatre op på siderne på webstedet ved hjælp af nogen smarte metoder, men blot bruge denne fil.

Sådan kontrolleres tilstedeværelsen af ​​denne fil: lad os analysere site.ru-webstedet, og gå derefter til site.ru/sitemap.xml i browseren - hvis du ser noget, så er det der, og hvis du ikke kan se det , så ak.

Hvis der er et sitemap, så indeholder det links til alle sider på webstedet i XML-format. Tag roligt denne XML, parse den, adskil links til de sider, du har brug for på nogen måde, der er praktisk for dig (for eksempel ved at parse URL'en, som blev beskrevet i spider-metoden).

Som et resultat får du en liste over links til parsing, du skal bare gå til dem og analysere det indhold, du har brug for.

Læs mere om sitemap.xml-enheden i Wikipedia.

Hvad skal du gøre nu:

Begynd at løse problemer på følgende link: opgaver til lektionen.

Når du har besluttet alt, så gå videre til at studere et nyt emne.


offentliggørelsen af ​​denne artikel er kun tilladt med et link til hjemmesiden for artiklens forfatter

I denne artikel vil jeg vise dig et eksempel på, hvordan du analyserer en stor XML-fil. Hvis din server (hosting) ikke forbyder en stigning i køretiden for scriptet, så kan du parse en XML-fil, der vejer mindst gigabyte, han parsede personligt kun filer fra ozon, der vejer 450 megabyte.

Der er to problemer ved parsing af store XML-filer:
1. Ikke nok hukommelse.
2. Der er ikke afsat tid nok til, at scriptet virker.

Det andet problem med tiden kan løses, hvis serveren ikke forbyder det.
Men problemet med hukommelse er svært at løse, selvom vi taler om din egen server, så er det ikke særlig nemt at flytte filer på 500 megabyte, og det er simpelthen ikke muligt at øge hukommelsen på hosting og på VDS.

PHP har flere indbyggede XML-behandlingsmuligheder - SimpleXML, DOM, SAX.
Alle disse muligheder er beskrevet i mange eksempelartikler, men alle eksempler demonstrerer arbejdet med et komplet XML-dokument.

Her er et eksempel på at få et objekt fra en XML-fil

Nu kan du behandle dette objekt, MEN ...
Som du kan se, læses hele XML-filen ind i hukommelsen, hvorefter alt parses til et objekt.
Det vil sige, at alle data går ind i hukommelsen, og hvis den tildelte hukommelse er lille, stopper scriptet.

Denne mulighed er ikke egnet til behandling af store filer, du skal læse filen linje for linje og behandle disse data på skift.
I dette tilfælde udføres validitetskontrollen på samme måde, som dataene behandles, så du skal kunne rulle tilbage, for eksempel slette alle de data, der er indtastet i databasen, hvis der er tale om en ugyldig XML-fil, eller lav to gennemløb gennem filen, læs først for gyldighed, læs derefter for at behandle data.

Her er et teoretisk eksempel på parsing af en stor XML-fil.
Dette script læser et tegn ad gangen fra filen, samler disse data i blokke og sender dem til XML-parseren.
Denne tilgang løser fuldstændigt hukommelsesproblemet og forårsager ikke stress, men forværrer problemet over tid. Hvordan du forsøger at løse problemet over tid, læs nedenfor.

Funktion webi_xml ($ fil)
{

########
### funktion til at arbejde med data

{
print $ data;
}
############################################



{
print $ navn;
print_r ($ attrs);
}


## sluttag-funktion
funktion endElement ($ parser, $ navn)
{
print $ navn;
}
############################################

($ xml_parser, "data");

// åbne filen
$ fp = fopen ($ fil, "r");

$ perviy_vxod = 1; $ data = "";



{

$ simvol = fgetc ($ fp); $ data. = $ simvol;


if ($ simvol! = ">") (fortsæt;)


ekko "

pause;
}

$ data = "";
}
fclose ($ fp);

Webi_xml ("1.xml");

?>

I dette eksempel har jeg lagt alt i én funktion webi_xml () og helt nederst kan du se dets kald.
Selve scriptet består af tre hovedfunktioner:
1. Funktionen, der fanger åbningen af ​​startElement () tag
2. En funktion, der fanger endElement ()-mærket ved at lukke
3. Og funktionen til at modtage datadata ().

Antag, at indholdet af filen 1.xml er en opskrift



< title >Simpelt brød
< ingredient amount = "3" unit = "стакан" >Mel
< ingredient amount = "0.25" unit = "грамм" >Gær
< ingredient amount = "1.5" unit = "стакан" >Varmt vand
< ingredient amount = "1" unit = "чайная ложка" >Salt
< instructions >
< step > Bland alle ingredienser og ælt grundigt.
< step > Dæk til med et klæde og lad stå i en time i et varmt rum..
< step > Ælt igen, læg på en bageplade og sæt i ovnen.
< step > Besøg webstedets websted


Vi starter det hele med at kalde den fælles funktion webi_xml ("1.xml");
Længere i denne funktion starter parseren, og alle tagnavne konverteres til store bogstaver, så alle tags har samme store og små bogstaver.

$ xml_parser = xml_parser_create ();
xml_parser_set_option ($ xml_parser, XML_OPTION_CASE_FOLDING, sand);

Nu angiver vi, hvilke funktioner der vil fungere til at fange åbningen af ​​tagget, lukke og behandle dataene

xml_set_element_handler ($ xml_parser, "startElement", "endElement");
xml_set_character_data_handler($ xml_parser, "data");

Dernæst kommer åbningen af ​​den angivne fil, der gentages over filen et tegn ad gangen, og hvert tegn føjes til strengvariablen, indtil tegnet er fundet > .
Hvis dette er den allerførste adgang til filen, så slettes undervejs alt, hvad der vil være overflødigt i starten af ​​filen, alt hvad der er før , dette er det tag, som XML skal starte med.
For første gang vil strengvariablen samle strengen

Og send hende til parseren
xml_parse ($ xml_parser, $ data, feof ($ fp));
Efter behandling af dataene kasseres strengvariablen, og dataindsamlingen i strengen starter igen, og strengen dannes en anden gang

I den tredje
</b><br>på den fjerde <br><b>Simpelt brød

Bemærk venligst, at strengvariablen altid dannes af det færdige tag > og det er ikke nødvendigt at sende et åbent og lukket tag med data til f.eks. edderkoppen
Simpelt brød
Det er vigtigt for denne handler at få et helt ikke-brudt tag, mindst et åbent tag, men i næste trin et lukket tag, eller straks få 1000 linjer af filen, det er ligegyldigt, det vigtigste er, at tagget går ikke i stykker f.eks

le> Simpelt brød
Du kan ikke sende data til handleren på denne måde, fordi tagget er gået i stykker.
Du kan finde på din egen metode til at sende data til handleren, for eksempel indsamle 1 megabyte data hver og sende til handleren for at øge hastigheden, bare sørg for at taggene altid er udfyldt og dataene kan brydes
Enkel</b><br><b>brød

Således kan du i dele, som du ønsker, sende en stor fil til handleren.

Lad os nu se på, hvordan disse data behandles, og hvordan man får dem.

Lad os starte med åbningstags-funktionen startElement ($ parser, $ navn, $ attrs)
Antag, at behandlingen har nået linjen
< ingredient amount = "3" unit = "стакан" >Mel
Derefter, inde i funktionen, vil variablen $ navn være lig med ingrediens det vil sige navnet på det åbne tag (det er ikke kommet til at lukke tagget endnu).
Også i dette tilfælde vil en række attributter for dette $ attrs-tag være tilgængelige, hvori der vil være data mængde = "3" og enhed = "glas".

Derefter behandles dataene fra det åbne tag med funktionen data ($ parser, $ data)
$ datavariablen vil indeholde alt mellem åbnings- og afsluttende tags, i vores tilfælde er dette teksten Flour

Og behandlingen af ​​vores streng fuldføres af funktionen endElement ($ parser, $ navn)
Dette er navnet på det lukkede tag, i vores tilfælde vil $ navn være lig med ingrediens

Og herefter gik alt i ring igen.

Ovenstående eksempel demonstrerer kun princippet om XML-behandling, men til reel brug skal det forbedres.
Normalt er det nødvendigt at parse stor XML for at indtaste data i databasen, og for korrekt databehandling skal du vide hvilket åbent tag dataene tilhører, hvilket tag-nesting-niveau og hvilke tags der er åbne i hierarkiet højere. Med disse oplysninger kan du behandle filen korrekt uden problemer.
For at gøre dette skal du indtaste flere globale variabler, der vil indsamle oplysninger om åbne tags, indlejring og data.
Her er et eksempel, som du kan bruge

Funktion webi_xml ($ fil)
{
global $ webi_depth; // tæller for at spore rededybden
$ webi_depth = 0;
global $ webi_tag_open; // vil indeholde en række af aktuelt åbne tags
$ webi_tag_open = matrix ();
global $ webi_data_temp; // dette array vil indeholde dataene for et tag

####################################################
### funktion til at arbejde med data
funktionsdata ($ parser, $ data)
{
global $ webi_depth;
global $ webi_tag_open;
global $ webi_data_temp;
// tilføj data til arrayet, der angiver det indlejrede og aktuelt åbne tag
$ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["data"]. = $ data;
}
############################################

####################################################
### åbning af tags funktion
funktion startElement ($ parser, $ navn, $ attrs)
{
global $ webi_depth;
global $ webi_tag_open;
global $ webi_data_temp;

// hvis indlejringsniveauet ikke længere er nul, er et tag allerede åbent
// og dataene fra det allerede er i arrayet, kan du behandle det
if ($ webi_depth)
{




" ;

Print "
" ;
print_r ($ webi_tag_open); // række åbne tags
Print "


" ;

// efter at have behandlet dataene, slet dem for at frigøre hukommelse
unset ($ GLOBALS ["webi_data_temp"] [$ webi_depth]);
}

// nu er åbningen af ​​næste tag startet, og videre behandling vil finde sted ved næste trin
$ webi_depth ++; // øge redegørelsen

$ webi_tag_open [$ webi_depth] = $ navn; // tilføj det åbne tag til informationsarrayet
$ webi_data_temp [$ webi_depth] [$ navn] ["attrs"] = $ attrs; // tilføj nu tag-attributterne

}
###############################################

#################################################
## sluttag-funktion
function endElement ($ parser, $ navn) (
global $ webi_depth;
global $ webi_tag_open;
global $ webi_data_temp;

// det er her databehandling starter, for eksempel tilføjelse til databasen, lagring til en fil osv.
// $ webi_tag_open indeholder en kæde af åbne tags efter indlejringsniveau
// for eksempel $ webi_tag_open [$ webi_depth] indeholder navnet på det åbne tag, hvis oplysninger i øjeblikket behandles
// $ webi_depth tag-nesting-niveau
// $ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["attrs"] række af tag-attributter
// $ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["data"] tag data

Udskriv "data". $ webi_tag_open [$ webi_depth]. "-". ($ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["data"]). "
" ;
print_r ($ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["attrs"]);
Print "
" ;
print_r ($ webi_tag_open);
Print "


" ;

Frakoblet ($ GLOBALS ["webi_data_temp"]); // efter at have behandlet dataene, slet hele arrayet med data, da tagget blev lukket
unset ($ GLOBALS ["webi_tag_open"] [$ webi_depth]); // fjern information om dette åbne tag ... siden det lukkede

$ webi_depth -; // mindske indlejring
}
############################################

$ xml_parser = xml_parser_create ();
xml_parser_set_option ($ xml_parser, XML_OPTION_CASE_FOLDING, sand);

// specificer hvilke funktioner der vil fungere, når du åbner og lukker tags
xml_set_element_handler ($ xml_parser, "startElement", "endElement");

// angiv en funktion til at arbejde med data
xml_set_character_data_handler($ xml_parser, "data");

// åbne filen
$ fp = fopen ($ fil, "r");

$ perviy_vxod = 1; // flag for at kontrollere den første filpost
$ data = ""; // her indsamler vi data fra filen i dele og sender dem til xml-parseren

// loop indtil slutningen af ​​filen er fundet
mens (! feof ($ fp) og $ fp)
{
$ simvol = fgetc ($ fp); // læs et tegn fra filen
$ data. = $ simvol; // tilføje dette symbol til de data, der skal sendes

// hvis tegnet ikke er et slutmærke, så går vi tilbage til begyndelsen af ​​løkken og tilføjer endnu et tegn til dataene, og så videre, indtil slutmærket er fundet
if ($ simvol! = ">") (fortsæt;)
// hvis et afsluttende tag blev fundet, send nu disse indsamlede data til behandling

// tjek om dette er den første indtastning i filen, og slet derefter alt, der er før tagget// da der nogle gange kan findes skrald før begyndelsen af ​​XML (klodsede editorer, eller filen modtages af et script fra en anden server)
if ($ perviy_vxod) ($ data = strstr ($ data, "

// nu smider vi dataene ind i xml-parseren
if (! xml_parse ($ xml_parser, $ data, feof ($ fp))) (

// her kan du behandle og få fejl for gyldighed ...
// Så snart der opstår en fejl, stopper parsingen
ekko "
XML-fejl: ". Xml_error_string (xml_get_error_code ($ xml_parser));
ekko "på linje". xml_get_current_line_number ($ xml_parser);
pause;
}

// efter parsing, kasser de indsamlede data til næste trin i cyklussen.
$ data = "";
}
fclose ($ fp);
xml_parser_free ($ xml_parser);
// fjern globale variabler
unset ($ GLOBALS ["webi_depth"]);
unset ($ GLOBALS ["webi_tag_open"]);
unset ($ GLOBALS ["webi_data_temp"]);

Webi_xml ("1.xml");

?>

Hele eksemplet var ledsaget af kommentarer, nu test og eksperimenter.
Bemærk venligst, at i funktionen med at arbejde med data, indsættes data ikke blot i et array, men tilføjes ved hjælp af " .=" da dataene måske ikke kommer i sin helhed, og hvis du laver en simpel opgave, så vil du fra tid til anden modtage data i bidder.

Nå, det er alt, nu er der nok hukommelse, når du behandler en fil af enhver størrelse, men scriptets køretid kan øges på flere måder.
Indsæt funktionen i begyndelsen af ​​scriptet
sæt_tidsgrænse (6000);
eller
ini_set ("max_execution_time", "6000");

Eller tilføj teksten til din .htaccess-fil
php_value max_execution_time 6000

Disse eksempler vil øge køretiden for scriptet til 6000 sekunder.
Du kan kun øge tiden på denne måde i deaktiveret tilstand.

Hvis du har adgang til edit php.ini kan du øge tiden med
max_execution_time = 6000

For eksempel på hosting-masterhosten i skrivende stund er det forbudt at øge scripttiden, på trods af den deaktiverede fejlsikret tilstand, men hvis du er en professionel, kan du lave din egen php-assembly på masterhosten, men det handler ikke om det i denne artikel.

Nogle af eksemplerne i denne øvelse inkluderer en XML-streng. I stedet for at gentage det i hvert eksempel, læg den linje i en fil, som du inkluderer i hvert eksempel. Denne linje er vist i følgende eksempel. Derudover kan du oprette et XML-dokument og læse det med funktionen simplexml_load_file ().

Eksempel # 1 Eksempel.php-fil med XML-streng

$ xmlstr =<<


PHP: Introduktion til parseren


Frk. Koder
Onlivia Actora


Hr. Koder
El ActÓr


Så det er et sprog. Det er stadig et programmeringssprog. Eller
er det et scriptsprog? Alt afsløres i denne dokumentar
som en gyserfilm.




7
5


XML;
?>

SimpleXML er let at bruge! Prøv at hente en streng eller et tal fra det underliggende XML-dokument.

Eksempel # 2 Hentning af en del af et dokument

inkludere "eksempel.php";

echo $ film -> film [0] -> plot;
?>

Så det er et sprog. Det er stadig et programmeringssprog. Eller er det et scriptsprog? Alt afsløres i denne horror-lignende dokumentar.

I PHP kan du få adgang til et element i et XML-dokument, der indeholder ugyldige tegn (såsom en bindestreg) i navnet ved at omslutte det givne elementnavn i krøllede parenteser og apostrof.

Eksempel # 3 Hentning af en streng

inkludere "eksempel.php";

echo $ film -> film -> ("store-linjer") -> linje;
?>

Resultatet af dette eksempel:

PHP løser alle mine webproblemer

Eksempel # 4 Adgang til ikke-unikke elementer i SimpleXML

I tilfælde af, at der er flere forekomster af underordnede elementer i et overordnet element, skal du bruge standard iterationsmetoderne.

inkludere "eksempel.php";

$ film = nyt SimpleXMLElement ($ xmlstr);

/ * For hver node , vil vi vise navnet separat . */
foreach ($ film -> film -> tegn -> karakter som $ karakter) (
echo $ karakter -> navn, "spiller", $ karakter -> skuespiller, PHP_EOL;
}

?>

Resultatet af dette eksempel:

Frk. Coder spillet af Onlivia Actora Mr. Coder spillet af El ActÓr

Kommentar:

Ejendomme ( $ film-> film i det foregående eksempel) er ikke arrays. Det er en iterabel som et array.

Eksempel # 5 Brug af attributter

Indtil nu har vi kun fået navne og værdier af elementerne. SimpleXML kan også få adgang til et elements attributter. En elementattribut kan tilgås på samme måde som matrixelementer ( array).

inkludere "eksempel.php";

$ film = nyt SimpleXMLElement ($ xmlstr);

/ * Adgang til noden den første film.
* Vi viser også vurderingsskalaen. * /
foreach ($ film -> film [0] -> vurdering som $ rating) (
switch ((streng) $ rating ["type"]) ( // Få elementets attributter efter indeks
case "thumbs":
echo $ rating, "thumbs up";
pause;
case "stjerner":
echo $ rating, "stjerner";
pause;
}
}
?>

Resultatet af dette eksempel:

7 thumbs up 5 stjerner

Eksempel #6 Sammenligning af elementer og attributter med tekst

For at sammenligne et element eller en attribut med en streng, eller for at overføre det til en funktion som tekst, skal du caste det til en streng vha. (snor)... Ellers vil PHP behandle elementet som et objekt.

inkludere "eksempel.php";

$ film = nyt SimpleXMLElement ($ xmlstr);

if ((streng) $ film -> film -> titel == "PHP: The Rise of the Parser") {
Print "Min yndlingsfilm.";
}

echo htmlentities ((streng) $ film -> film -> titel);
?>

Resultatet af dette eksempel:

Min yndlingsfilm Php: The Emergence of the Parser

Eksempel # 7 Sammenligning af to elementer

To SimpleXMLElements betragtes som forskellige, selvom de peger på det samme objekt siden PHP 5.2.0.

inkludere "eksempel.php";

$ movies1 = nyt SimpleXMLElement ($ xmlstr);
$ movies2 = nyt SimpleXMLElement ($ xmlstr);
var_dump ($ film1 == $ film2); // falsk siden PHP 5.2.0
?>

Resultatet af dette eksempel:

Eksempel # 8 Brug af XPath

SimpleXML inkluderer indbygget XPath-understøttelse. Find alle varer :

inkludere "eksempel.php";

$ film = nyt SimpleXMLElement ($ xmlstr);

foreach ($ film -> xpath ("// karakter") som $ karakter) (
echo $ karakter -> navn, "spiller", $ karakter -> skuespiller, PHP_EOL;
}
?>

"// "fungerer som en skabelon. For at angive en absolut sti skal du udelade en af ​​skråstregene.

Resultatet af dette eksempel:

Frk. Coder spillet af Onlivia Actora Mr. Coder spillet af El ActÓr

Eksempel # 9 Indstillingsværdier

Data i SimpleXML behøver ikke at være uforanderlige. Objektet giver dig mulighed for at manipulere alle elementer.

inkludere "eksempel.php";
$ film = nyt SimpleXMLElement ($ xmlstr);

$ film -> film [0] -> karakterer -> karakter [0] -> navn = "Miss Coder";

echo $ film -> asXML ();
?>

Resultatet af dette eksempel:

PHP: Introduktion til parseren Frøken koder Onlivia Actora Hr. Koder El ActÓr 7 5

Eksempel # 10 Tilføjelse af elementer og attributter

Siden PHP 5.1.3 har SimpleXML muligheden for nemt at tilføje underordnede elementer og attributter.

inkludere "eksempel.php";
$ film = nyt SimpleXMLElement ($ xmlstr);

$ karakter = $ film -> film [0] -> tegn -> addChild ("karakter");
$ karakter -> addChild ("navn", "Mr. Parser");
$ karakter -> addChild ("skuespiller", "John Doe");

$ rating = $ film -> film [0] -> addChild ("rating", "PG");
$ rating -> addAttribute ("type", "mpaa");

echo $ film -> asXML ();
?>

Resultatet af dette eksempel:

PHP: Introduktion til parseren Frk. Koder Onlivia Actora Hr. Koder El ActÓr Hr. ParserJohn Doe Så det er et sprog. Det er stadig et programmeringssprog. Eller er det et scriptsprog? Alt afsløres i denne horror-lignende dokumentar. PHP løser alle mine webopgaver 7 5 PG

Eksempel # 11 Interaktion med DOM

PHP kan konvertere XML-noder fra SimpleXML til DOM-format og omvendt. Dette eksempel viser, hvordan du kan ændre et DOM-element i SimpleXML.

$ dom = nyt DOMDocument;
$ dom -> loadXML ( "nonsens" );
hvis (! $ dom) (
ekko "Der opstod en fejl under parsing af dokumentet";
Afslut;
}

$ bøger = simplexml_import_dom ($ dom);

echo $ bøger -> bog [0] -> titel;
?>

Resultatet af dette eksempel:

for 4 år siden

Der er et almindeligt "trick", der ofte foreslås til at konvertere et SimpleXML-objekt til et array ved at køre det gennem json_encode () og derefter json_decode (). Jeg vil gerne forklare, hvorfor det er en dårlig idé.

Mest simpelt, fordi hele pointen med SimpleXML er at være nemmere at bruge og mere kraftfuld end et almindeligt array. For eksempel kan du skrivebar -> baz ["bing"]?> og det betyder det samme sombar [0] -> baz [0] ["bing"]?>, uanset hvor mange bar eller baz-elementer der er i XML; og hvis du skriverbar [0] -> baz [0]?> får du alt strengindholdet i den node - inklusive CDATA-sektioner - uanset om den også har underordnede elementer eller attributter. Du har også adgang til navnerumsinformation, muligheden for at lave simple redigeringer af XML'en og endda muligheden for at "importere" til et DOM-objekt for meget mere kraftfuld manipulation. Alt dette går tabt ved at omdanne objektet til et array i stedet for at læse og forstå eksemplerne på denne side.

Derudover, fordi den ikke er designet til dette formål, vil konverteringen til JSON og tilbage faktisk miste information i nogle situationer. For eksempel vil alle elementer eller attributter i et navneområde simpelthen blive kasseret, og alt tekstindhold vil blive kasseret, hvis et element også har underordnede eller attributter. Nogle gange betyder det ikke noget, men hvis du vænner dig til at konvertere alt til arrays, kommer det til at svie dig til sidst.

Selvfølgelig kunne du skrive en smartere konvertering, som "ikke havde disse begrænsninger, men på det tidspunkt får du overhovedet ingen værdi ud af SimpleXML, og du skal bare bruge XML Parser-funktionerne på lavere niveau eller XMLReader-klassen, for at skabe din struktur. Du vil stadig "ikke have den ekstra bekvemmelighedsfunktionalitet som SimpleXML, men det" er dit tab.

2 år siden

Hvis din xml-streng indeholder booleaner kodet med "0" og "1", vil du løbe ind i problemer, når du caster elementet direkte til bool:

$ xmlstr =<<

1
0

XML;
$ værdier = nyt SimpleXMLElement ($ xmlstr);
$ truevalue = (bool) $ values-> truevalue; // rigtigt
$ falsevalue = (bool) $ values-> falsevalue; // også sandt!!!

I stedet skal du først caste til streng eller int:

$ truevalue = (bool) (int) $ values-> truevalue; // rigtigt
$ falsevalue = (bool) (int) $ values-> falsevalue; // falsk

9 år siden

Hvis du har brug for at udlæse gyldig xml i dit svar, så glem ikke at indstille din header-indholdstype til xml ud over at ekko resultatet af asXML ():

$ xml = simplexml_load_file ("...");
...
... xml-ting
...

// output xml i dit svar:
header ("Indholdstype: tekst / xml");
echo $ xml -> asXML ();
?>

9 år siden

Fra README-filen:

SimpleXML er beregnet til at være en nem måde at få adgang til XML-data på.

SimpleXML-objekter følger fire grundlæggende regler:

1) egenskaber angiver element-iteratorer
2) numeriske indekser angiver elementer
3) ikke-numeriske indekser angiver attributter
4) strengkonvertering giver adgang til TEKST-data

Ved iteration af egenskaber gentager udvidelsen altid
alle noder med det elementnavn. Således metode børn () skal være
kaldet til at iterere over subnoder. Men gør også følgende:
foreach ($ obj-> node_name som $ elem) (
// gør noget med $ elem
}
resulterer altid i iteration af "node_name"-elementer. Så ikke længere
kontrol er nødvendig for at skelne antallet af noder af den type.

Når et element TEXT-data tilgås via en egenskab
så inkluderer resultatet ikke TEXT-dataene for underelementer.

Kendte problemer
============

På grund af motorproblemer er det i øjeblikket ikke muligt at få adgang
et underelement ved indeks 0: $ objekt-> egenskab.

8 år siden

Brug af ting som: is_object ($ xml-> modul-> admin) for at kontrollere, om der faktisk er en node kaldet "admin", virker "ikke som forventet, da simplexml altid returnerer et objekt - i så fald et tomt" - også selvom en bestemt node ikke eksisterer.
For mig ser den gode gamle tomme () funktion ud til at fungere fint i sådanne tilfælde.

8 år siden

Et hurtigt tip om xpath-forespørgsler og standardnavneområder. Det ser ud til, at XML-systemet bag SimpleXML fungerer på samme måde, som jeg tror, ​​XML-systemet .NET bruger: når man skal adressere noget i standardnavnerummet, bliver man nødt til at erklære navnerummet ved hjælp af registerXPathNamespace og derefter bruge dets præfiks til adressere ellers i standardnavnerummet levende element.

$ streng =<<

Fyrre Hvad?
Joe
Jane

Jeg ved, at "svaret er - men hvad" er spørgsmålet?




XML;

$ xml = simplexml_load_string ($ streng);
$ xml -> registerXPathNamespace ("def", "http://www.w3.org/2005/Atom");

$ noder = $ xml -> xpath ("// def: document / def: title");

?>

9 år siden

Mens SimpleXMLElement hævder at være iterable, ser det ikke ud til at implementere standard Iterator-grænsefladefunktionerne som :: next og :: nulstillet korrekt. Mens foreach () virker, virker som næste (), nuværende () eller hver () derfor ikke til at fungere, som du ville forvente - viseren ser aldrig ud til at bevæge sig eller bliver ved med at blive nulstillet.

6 år siden

Hvis kodningen af ​​XML-dokumentet er forskellig fra UTF-8, skal kodningserklæringen følge umiddelbart efter version = "..." og før standalone = "...". Dette er et krav i XML-standarden.

Hvis kodning af XML-dokument adskiller sig fra UTF-8. Kodningserklæringen skal følge umiddelbart efter versionen = "..." og før standalone = "...". Dette krav er standard XML.


Okay

Russisk sprog. russisk sprog


Fatal fejl: Uopfanget undtagelse "Exception" med meddelelsen "String could not be parsed as XML" in ...

Extensible Markup Language XML er et sæt regler for kodning af dokumenter i maskinlæsbar form. XML er et populært format til udveksling af data på internettet. Websteder, der ofte opdaterer deres indhold, såsom nyhedswebsteder eller blogs, leverer ofte et XML-feed for at holde eksterne programmer opmærksomme på indholdsændringer. Afsendelse og parsing af XML-data er en almindelig opgave for netværksapplikationer. Denne lektion forklarer, hvordan man parser XML-dokumenter og bruger deres data.

Valg af en parser

Kanalanalyse

Det første trin i at parse et feed er at beslutte, hvilke datafelter du er interesseret i. Parseren udtrækker de angivne felter og ignorerer alt andet.

Her er et feed-uddrag, der vil blive udforsket i eksempelapplikationen. Hvert indlæg på StackOverflow.com vises i feedet som et indgangstag, der indeholder flere indlejrede tags:

nyeste spørgsmål tagget android - Stack Overflow ... ... http://stackoverflow.com/q/9439999 0 Hvor er min datafil? cliff2310 http://stackoverflow.com/users/1128925 2012-02-25T00: 30: 54Z 2012-02-25T00: 30: 54Z

Jeg har et program, der kræver en datafil ...

... ...

Eksempelappen udtrækker data fra indgangstagget og dets undertags titel, link og oversigt.

Instantiering af parseren

Det næste trin er at instansiere parseren og starte parsingsprocessen. Dette uddrag initialiserer parseren til ikke at håndtere navneområder og bruger den leverede InputStream som input. Parsingprocessen startes ved at kalde nextTag () og kalder readFeed () metoden, som henter og behandler de data, applikationen er interesseret i:

Offentlig klasse StackOverflowXmlParser (// Vi bruger ikke navnerum private static final String ns = null; public List parse (InputStream in) kaster XmlPullPullParserException, IOException (try (XmlPullParser parser = Xml.newPullParser (); parsull_arsersetParserset.Xml. ); parser.setInput (in, null); parser.nextTag (); returner readFeed (parser);) til sidst (in.close ();)) ...)

Træk kanal fra

ReadFeed () metoden udfører selve arbejdet med at håndtere feedet. Elementer markeret med "entry"-tagget er udgangspunktet for rekursiv kanalbehandling. Hvis det næste mærke ikke er et indgangsmærke, springes det over. Når hele feedet er blevet rekursivt behandlet, returnerer readFeed () en liste, der indeholder de indgange (inklusive indlejrede dataelementer), der hentes fra feedet. Denne liste returneres derefter af parseren.

Private List readFeed (XmlPullParser parser) kaster XmlPullParserException, IOException (List entries = new ArrayList (); parser.require (XmlPullParser.START_TAG, ns, "feed"); while (parser.next ()! = Xmlser.END_Pull getEventType ()! = XmlPullParser.START_TAG) (fortsæt;) Strengnavn = parser.getName (); // Starter med at lede efter entry-tagget if (name.equals ("entry")) (entries.add ( readEntry (parser) ));) else (spring over (parser);)) returnere poster;)

Parsing af XML

Trinene til at parse et XML-feed er som følger:

Dette uddrag viser, hvordan parseren analyserer indgang, titel, link og oversigt.

Offentlig statisk klasseindgang (offentlig endelig strengtitel; offentlig endelig strenglink; offentlig endelig strengoversigt; privat post (strengtitel, strengoversigt, strenglink) (this.title = titel; this.summary = resumé; this.link = link ;)) // Parser indholdet af en post. Hvis den støder på en titel, et resumé eller et link-tag, skal du videregive dem // til deres respektive "læse"-metoder til behandling. Ellers springer tagget over. private Entry readEntry (XmlPullParser parser) kaster XmlPullParserException, IOException (parser.require (XmlPullParser.START_TAG, ns, "entry"); String title = null; String summary = null; String link = null.next (parser!) = XmlPullParser.END_TAG) (if (parser.getEventType ()! = XmlPullParser.START_TAG) (fortsæt;) String name = parser.getName (); if (name.equals ("title")) (title = readTitle (parser) ;) else if (name.equals ("resumé")) (summary = readSummary (parser);) else if (name.equals ("link")) (link = readLink (parser);) else (spring over (parser) ;)) returner ny indgang (titel, resumé, link);) // Behandler title tags i feedet. private String readTitle (XmlPullParser parser) kaster IOException, XmlPullParserException (parser.require (XmlPullParser.START_TAG, ns, "title"); String title = readText (parser); parser.require (XmlPullParser"); return.END "title"; ) // Behandler link-tags i feedet. private String readLink (XmlPullParser parser) kaster IOException, XmlPullParserException (String link = ""; parser.require (XmlPullParser.START_TAG, ns, "link"); String tag = parser.getName (); String triburelType = parser.getueA (tnullteValueA) , "rel"); if (tag.equals ("link")) (if (relType.equals ("alternate")) (link = parser.getAttributeValue (null, "href"); parser.nextTag ();) ) parser.require (XmlPullParser.END_TAG, ns, "link"); return link;) // Behandler summary tags i feedet. private String readSummary (XmlPullParser parser) kaster IOException, XmlPullParserException (parser.require (XmlPullParser.START_TAG, ns, "summary"); String summary = readText (parser); parser.require (XmlPullPar summary, "END_TAG summary"); ) // For tags titel og oversigt, udtrækker deres tekstværdier. private String readText (XmlPullParser parser) kaster IOException, XmlPullParserException (String result = ""; if (parser.next () == XmlPullParser.TEXT) (result = parser.getText (); parser.nextTag ();) returner resultat; ) ...)

Springer varer over, du ikke har brug for

I et af XML-parsing-trinene beskrevet ovenfor springer parseren tags over, som vi ikke er interesserede i. Nedenfor er koden for skip ()-metodens parser:

Privat void spring (XmlPullParser parser) kaster XmlPullParserException, IOException (if (parser.getEventType ()! = XmlPullParser.START_TAG) (smid ny IllegalStateException ();) int depth = 1; while (parserswitch! = (0)) næste ()) (case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.START_TAG: depth ++; break;)))

Sådan fungerer det:

  • Metoden kaster en undtagelse, hvis den aktuelle hændelse ikke er START_TAG.
  • Den bruger START_TAG og alle begivenheder op til END_TAG.
  • For at sikre, at det stopper ved det korrekte END_TAG og ikke det første møde-tag efter det oprindelige START_TAG, holder det styr på rededybden.

Hvis det aktuelle element har indlejrede elementer, vil dybdeværdien ikke være 0, før parseren har behandlet alle hændelser mellem den oprindelige START_TAG og dens tilsvarende END_TAG. Overvej for eksempel, hvordan analysatoren misser et element, der har 2 indlejrede elementer, og :

  • I den første passage gennem while-løkken, den næste tag, som analysatoren støder på efter dette er START_TAG for
  • I den anden passage gennem while-løkken er det næste tag, som analysatoren støder på, END_TAG
  • I den tredje passage gennem while-løkken er det næste tag, som analysatoren støder på, START_TAG ... Dybdeværdien øges til 2.
  • I den fjerde passage gennem while-løkken er det næste tag, som analysatoren støder på, END_TAG... Dybdeværdien falder til 1.
  • På den femte og sidste passage gennem while-løkken er det næste tag, som analysatoren støder på, END_TAG... Dybden falder til 0, hvilket indikerer det elementet blev sprunget over.

XML databehandling

Eksempelapplikationen modtager og analyserer et XML-feed til en AsyncTask. Behandling udføres uden for hovedgrænsefladetråden. Når behandlingen er færdig, opdaterer applikationen brugergrænsefladen i hovedaktiviteten (NetworkActivity).

I uddraget nedenfor gør loadPage ()-metoden følgende:

  • Initialiserer en strengvariabel med en URL-værdi, der peger på et XML-feed.
  • Hvis brugerindstillinger og netværksforbindelse tillader det, kalder ny DownloadXmlTask ​​​​(). Udfør (url). Dette opretter et nyt DownloadXmlTask-objekt (AsyncTask-underklasse) og udfører dets execute ()-metode, som downloader og analyserer kanalen og returnerer et strengresultat, der vil blive vist i brugergrænsefladen.
offentlig klasse NetworkActivity udvider aktivitet (offentlig statisk endelig streng WIFI = "Wi-Fi"; offentlig statisk endelig streng ANY = "Enhver"; privat statisk endelig streng URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort = nyeste "; // Om der er en Wi-Fi-forbindelse. private static boolean wifiConnected = false; // Om der er en mobilforbindelse. private static boolean mobileConnected = false; // Om skærmen skal opdateres. public static boolean refreshDisplay = true; public static String sPref = null; ... // Bruger AsyncTask til at downloade XML-feedet fra stackoverflow.com. public void loadPage () (hvis ((sPref.equals (ANY)) && (wifiConnected || mobileConnected )) (ny DownloadXmlTask​(). execute (URL);) else if ((sPref.equals (WIFI)) && (wifiConnected)) (ny DownloadXmlTask​(). execute (URL);) else (// vis fejl))
  • doInBackground () udfører metoden loadXmlFromNetwork (). Den videregiver kanalens URL som en parameter. Metoden loadXmlFromNetwork () modtager og behandler kanalen. Når den er færdig med at behandle, sender den den resulterende streng tilbage.
  • onPostExecute () tager den returnerede streng og viser den i brugergrænsefladen.
// Implementering af AsyncTask bruges til at downloade XML-feed fra stackoverflow.com. privat klasse DownloadXmlTask ​​udvider AsyncTask (@Override beskyttet String doInBackground (String ... urls) (prøv (return loadXmlFromNetwork (urls);) catch (IOException e) (retur getResources (). GetString (R.string.connection_error);) catch (XmlPullParserException e) ( return getResources (). getString (R.string.xml_error);)) @Override protected void onPostExecute (String result) (setContentView (R.layout.main); // Viser HTML-strengen i brugergrænsefladen via en WebView WebView myWebView = (WebView) findViewById (R.id.webview); myWebView.loadData (resultat, "tekst / html", null);))

Nedenfor er loadXmlFromNetwork () metoden, som kaldes fra DownloadXmlTask. Den gør følgende:

  1. Opretter en forekomst af StackOverflowXmlParser. Det opretter også variabler for List Entry-objekter (indgange) og titel, url og oversigt for at gemme værdierne hentet fra XML-feedet for disse felter.
  2. Kalder downloadUrl (), som downloader kanalen og returnerer den som en InputStream.
  3. Bruger StackOverflowXmlParser til at parse InputStream. StackOverflowXmlParser udfylder listeposterne med data fra feedet.
  4. Behandler en indgangsliste og kombinerer feeddata med HTML-markering.
  5. Returnerer HTML-strengen vist i brugergrænsefladen for hovedaktiviteten, AsyncTask i metoden onPostExecute ().
// Uploader XML fra stackoverflow.com, analyserer det og kombinerer det med // HTML-markering. Returnerer HTML-streng. private String loadXmlFromNetwork (String urlString) kaster XmlPullParserException, IOException (InputStream stream = null; // Instantiér parseren StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser (); indgange = null; Strengtitel = null; String url = null; String summary = null; Calendar rightNow = Calendar.getInstance (); DateFormat formatter = new SimpleDateFormat ("MMM dd h: mmaa"); // Kontrollerer, om brugeren indstiller præferencen til at inkludere oversigtstekst SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences (dette); boolean pref = sharedPrefs.getBoolean ("summaryPref", falsk); StringBuilder htmlString = new StringBuilder (); htmlString.append ("

"+ getResources (). getString (R.string.page_title) +"

"); htmlString.append (" "+ getResources (). getString (R.string.updated) +" "+ formatter.format (rightNow.getTime ()) +""); prøv (stream = downloadUrl (urlString); entries = stackOverflowXmlParser.parse (stream); // Sørger for, at InputStream er lukket, efter at appen er // færdig med at bruge den.) til sidst (hvis (stream! = null) (stream.close ();)) // StackOverflowXmlParser returnerer en liste (kaldet "indgange") over indgangsobjekter. // Hvert indgangsobjekt repræsenterer et enkelt indlæg i XML-feedet. // Dette afsnit behandler indgangslisten for at kombinere hver indgang med HTML-markering. // Hver indgang vises i brugergrænsefladen som et link, der eventuelt inkluderer // et tekstresumé. for (indgang: indgange) (htmlString.append ("

"+ entry.title +"

"); // Hvis brugeren indstiller præferencen til at inkludere opsummeringstekst, // tilføjer den til displayet. Hvis (pref) (htmlString.append (entry.summary);)) returner htmlString.toString ();) // Givet en strengrepræsentation af en URL, opretter en forbindelse og får // en inputstream.private InputStream downloadUrl (String urlString) kaster IOException (URL url = new URL (urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection () ; conn.setReadTimeout (10000 / * milliseconds * /); conn.setConnectTimeout (15000 / * milliseconds * /); conn.setRequestMethod ("GET"); conn.setDoInput (true); // Starter forespørgslen conn.connect ( ); returner conn.getInputStream ();)