Analyserar xml-filen. Parsar XML



publicering av denna artikel är endast tillåten med en länk till webbplatsen för artikelförfattaren

I den här artikeln kommer jag att visa dig ett exempel på hur man analyserar en stor XML-fil. Om din server (hosting) inte förbjuder en ökning av körtiden för skriptet, kan du analysera en XML-fil som väger minst gigabyte, han analyserade personligen endast filer från ozon som vägde 450 megabyte.

Det finns två problem när man analyserar stora XML-filer:
1. Inte tillräckligt med minne.
2. Det finns inte tillräckligt med tid för att skriptet ska fungera.

Det andra problemet med tid kan lösas om servern inte förbjuder det.
Men problemet med minne är svårt att lösa, även om vi pratar om din egen server, då är det inte särskilt lätt att flytta filer på 500 megabyte, och det går helt enkelt inte att öka minnet på hosting och på VDS.

PHP har flera inbyggda XML-behandlingsalternativ - SimpleXML, DOM, SAX.
Alla dessa alternativ beskrivs i många exempelartiklar, men alla exempel visar att du arbetar med ett komplett XML-dokument.

Här är ett exempel, att hämta ett objekt från en XML-fil

Nu kan du bearbeta detta objekt, MEN ...
Som du kan se läses hela XML-filen in i minnet, sedan tolkas allt till ett objekt.
Det vill säga, all data går in i minnet, och om det tilldelade minnet är litet, stoppar skriptet.

Det här alternativet är inte lämpligt för att bearbeta stora filer, du måste läsa filen rad för rad och bearbeta dessa data i tur och ordning.
I det här fallet utförs giltighetskontrollen på samma sätt som uppgifterna bearbetas, så du behöver kunna återställa t.ex. radera all data som lagts in i databasen vid en ogiltig XML-fil, eller gör två genomgångar genom filen, läs först för giltighet och läs sedan för bearbetning av data.

Här är ett teoretiskt exempel på att analysera en stor XML-fil.
Det här skriptet läser ett tecken i taget från filen, sätter ihop dessa data i block och skickar dem till XML-tolken.
Detta tillvägagångssätt löser helt minnesproblemet och orsakar inte stress, utan förvärrar problemet med tiden. Hur du försöker lösa problemet över tid, läs nedan.

Funktion webi_xml ($-fil)
{

########
### funktion för att arbeta med data

{
skriva ut $ data;
}
############################################



{
skriv ut $ namn;
print_r ($ attrs);
}


## sluttagsfunktion
function endElement ($ parser, $ namn)
{
skriv ut $ namn;
}
############################################

($ xml_parser, "data");

// öppna filen
$ fp = fopen ($ fil, "r");

$ perviy_vxod = 1; $ data = "";



{

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


if ($ simvol! = ">") (fortsätt;)


eko"

ha sönder;
}

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

Webi_xml ("1.xml");

?>

I det här exemplet lägger jag allt i en funktion webi_xml () och längst ner kan du se dess anrop.
Själva skriptet består av tre huvudfunktioner:
1. Funktionen som fångar öppningen av startElement () taggen
2. En funktion som fångar taggen endElement () när den stängs
3. Och funktionen att ta emot datadata ().

Anta att innehållet i filen 1.xml är något recept



< title >Enkelt bröd
< ingredient amount = "3" unit = "стакан" >Mjöl
< ingredient amount = "0.25" unit = "грамм" >Jäst
< ingredient amount = "1.5" unit = "стакан" >Varmvatten
< ingredient amount = "1" unit = "чайная ложка" >Salt
< instructions >
< step > Blanda alla ingredienser och knåda ordentligt.
< step > Täck med en trasa och låt stå i en timme i ett varmt rum..
< step > Knåda igen, lägg på en plåt och sätt in i ugnen.
< step > Besök webbplatsens webbplats


Vi börjar med att anropa den gemensamma funktionen webi_xml ("1.xml");
Längre in i denna funktion startar parsern och alla taggnamn konverteras till versaler så att alla taggar har samma skiftläge.

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

Nu anger vi vilka funktioner som kommer att fungera för att fånga öppningen av taggen, stänga och bearbeta data

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

Därefter kommer öppningen av den angivna filen, itererande över filen ett tecken i taget, och varje tecken läggs till i strängvariabeln tills tecknet hittas > .
Om detta är den allra första åtkomsten till filen, så kommer allt som kommer att vara överflödigt i början av filen att raderas, allt som är innan , det här är taggen som XML ska börja med.
För första gången kommer strängvariabeln att samla in strängen

Och skicka henne till analysen
xml_parse ($ xml_parser, $ data, feof ($ fp));
Efter bearbetning av data kasseras strängvariabeln och datainsamlingen i strängen börjar igen och strängen bildas en andra gång

I den tredje
</b><br>den fjärde <br><b>Enkelt bröd

Observera att strängvariabeln alltid bildas av den färdiga taggen > och det är inte nödvändigt att skicka en öppen och stängd tagg med data till spindeln till exempel
Enkelt bröd
Det är viktigt för denna hanterare att få en hel inte trasig tagg, åtminstone en öppen tagg, men i nästa steg en stängd tagg, eller omedelbart få 1000 rader av filen, det spelar ingen roll, huvudsaken är att taggen går inte sönder till exempel

le> Enkelt bröd
Du kan inte skicka data till hanteraren på det här sättet, eftersom taggen har gått sönder.
Du kan komma på din egen metod för att skicka data till hanteraren, till exempel samla in 1 megabyte data var och skicka till hanteraren för att öka hastigheten, se bara till att taggarna alltid är ifyllda och att data kan brytas
Enkel</b><br><b>bröd

Således, i delar som du vill, kan du skicka en stor fil till hanteraren.

Låt oss nu titta på hur denna data bearbetas och hur man får den.

Låt oss börja med öppningstaggarfunktionen startElement ($ parser, $ namn, $ attrs)
Antag att bearbetningen har nått linjen
< ingredient amount = "3" unit = "стакан" >Mjöl
Sedan, inuti funktionen, kommer variabeln $ namn att vara lika med ingrediens det vill säga namnet på den öppna taggen (det har inte kommit till att stänga taggen än).
I det här fallet kommer en rad attribut för denna $ attrs-tagg att vara tillgängliga, i vilka det kommer att finnas data mängd = "3" och enhet = "glas".

Efter det, bearbetningen av data från den öppna taggen med funktionen data ($ parser, $ data)
Datavariabeln $ kommer att innehålla allt mellan öppnings- och avslutande taggar, i vårt fall är detta texten Flour

Och bearbetningen av vår sträng slutförs av funktionen endElement ($ parser, $ namn)
Detta är namnet på den stängda taggen, i vårt fall kommer $ name att vara lika med ingrediens

Och efter det gick allt i ring igen.

Ovanstående exempel visar bara principen för XML-bearbetning, men för verklig användning behöver den förbättras.
Vanligtvis måste du analysera stor XML för att lägga in data i databasen, och för korrekt databehandling behöver du veta vilken öppen tagg data tillhör, vilken taggkapslingsnivå och vilka taggar som är öppna i hierarkin högre upp. Med denna information kan du bearbeta filen korrekt utan problem.
För att göra detta måste du ange flera globala variabler som samlar in information om öppna taggar, kapsling och data.
Här är ett exempel som du kan använda

Funktion webi_xml ($-fil)
{
global $ webi_depth; // räknare för att spåra häckningsdjupet
$ webi_depth = 0;
global $ webi_tag_open; // kommer att innehålla en uppsättning för närvarande öppna taggar
$ webi_tag_open = array ();
global $ webi_data_temp; // denna array kommer att innehålla data för en tagg

####################################################
### funktion för att arbeta med data
funktionsdata ($ parser, $ data)
{
global $ webi_depth;
global $ webi_tag_open;
global $ webi_data_temp;
// lägg till data till arrayen som indikerar den kapslade och för närvarande öppna taggen
$ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["data"]. = $ data;
}
############################################

####################################################
### öppningstaggarfunktion
funktion startElement ($ parser, $ namn, $ attrs)
{
global $ webi_depth;
global $ webi_tag_open;
global $ webi_data_temp;

// om kapslingsnivån inte längre är noll är en tagg redan öppen
// och data från den redan finns i arrayen, du kan bearbeta den
if ($ webi_depth)
{




" ;

skriv ut "
" ;
print_r ($ webi_tag_open); // rad öppna taggar
skriv ut "


" ;

// efter bearbetning av data, radera den för att frigöra minne
unset ($ GLOBALS ["webi_data_temp"] [$ webi_depth]);
}

// nu har öppnandet av nästa tagg börjat och vidare bearbetning kommer att ske i nästa steg
$ webi_depth ++; // öka häckningen

$ webi_tag_open [$ webi_depth] = $ namn; // lägg till den öppna taggen i informationsfältet
$ webi_data_temp [$ webi_depth] [$ namn] ["attrs"] = $ attrs; // lägg nu till taggattributen

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

#################################################
## sluttagsfunktion
function endElement ($ parser, $ namn) (
global $ webi_depth;
global $ webi_tag_open;
global $ webi_data_temp;

// det är här databehandlingen startar, till exempel lägga till i databasen, spara till en fil osv.
// $ webi_tag_open innehåller en kedja av öppna taggar efter kapslingsnivå
// till exempel $ webi_tag_open [$ webi_depth] innehåller namnet på den öppna taggen vars information för närvarande bearbetas
// $ webi_depth taggen kapslingsnivå
// $ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["attrs"] rad med taggattribut
// $ webi_data_temp [$ webi_depth] [$ webi_tag_open [$ webi_depth]] ["data"] taggdata

Skriv ut "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"]);
skriv ut "
" ;
print_r ($ webi_tag_open);
skriv ut "


" ;

Avaktiverad ($ GLOBALS ["webi_data_temp"]); // efter att ha bearbetat data, radera hela arrayen med data, eftersom taggen stängdes
unset ($ GLOBALS ["webi_tag_open"] [$ webi_depth]); // ta bort information om denna öppna tagg ... eftersom den stängdes

$ webi_depth -; // minska häckningen
}
############################################

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

// specificera vilka funktioner som ska fungera när taggar öppnas och stänger
xml_set_element_handler ($ xml_parser, "startElement", "endElement");

// ange en funktion för att arbeta med data
xml_set_character_data_handler($ xml_parser, "data");

// öppna filen
$ fp = fopen ($ fil, "r");

$ perviy_vxod = 1; // flagga för att kontrollera den första filposten
$ data = ""; // här samlar vi in ​​data från filen i delar och skickar den till xml-parsern

// loop tills slutet av filen hittas
medan (! feof ($ fp) och $ fp)
{
$ simvol = fgetc ($ fp); // läs ett tecken från filen
$ data. = $ simvol; // lägg till denna symbol i data som ska skickas

// om tecknet inte är en sluttagg, går vi tillbaka till början av loopen och lägger till ytterligare ett tecken till data, och så vidare tills sluttaggen hittas
if ($ simvol! = ">") (fortsätt;)
// om en avslutande tagg hittades, skicka nu denna insamlade data för bearbetning

// kontrollera om detta är den första posten i filen, ta sedan bort allt som finns före taggen// eftersom ibland skräp kan hittas före början av XML (klumpiga redigerare, eller filen tas emot av ett skript från en annan server)
if ($ perviy_vxod) ($ data = strstr ($ data, "

// nu slänger vi data i xml-parsern
if (! xml_parse ($ xml_parser, $ data, feof ($ fp))) (

// här kan du bearbeta och få fel för giltighet ...
// så snart ett fel påträffas, slutar tolkningen
eko"
XML-fel: ". Xml_error_string (xml_get_error_code ($ xml_parser));
eko "vid linjen". xml_get_current_line_number ($ xml_parser);
ha sönder;
}

// efter analys, kassera insamlade data för nästa steg i cykeln.
$ data = "";
}
fclose ($ fp);
xml_parser_free ($ xml_parser);
// ta bort globala variabler
unset ($ GLOBALS ["webi_depth"]);
unset ($ GLOBALS ["webi_tag_open"]);
unset ($ GLOBALS ["webi_data_temp"]);

Webi_xml ("1.xml");

?>

Hela exemplet åtföljdes av kommentarer, nu testa och experimentera.
Observera att i funktionen att arbeta med data infogas data inte bara i en array, utan läggs till med " .=" eftersom datan kanske inte kommer i sin helhet och om du gör en enkel uppgift så får du då och då data i bitar.

Tja, det är allt, nu finns det tillräckligt med minne när man bearbetar en fil av valfri storlek, men skriptets körtid kan ökas på flera sätt.
Infoga funktionen i början av skriptet
set_time_limit (6000);
eller
ini_set ("max_exekveringstid", "6000");

Eller lägg till texten i din .htaccess-fil
php_value max_execution_time 6000

Dessa exempel kommer att öka körtiden för skriptet till 6000 sekunder.
Du kan bara öka tiden på detta sätt i avaktiverat läge.

Om du har tillgång till edit php.ini kan du öka tiden med
max_execution_time = 6000

Till exempel, på värdmästarvärden när detta skrivs är det förbjudet att öka skripttiden, trots det inaktiverade felsäkert läge, men om du är ett proffs kan du göra din egen php-assembly på mastervärden, men det handlar inte om det i den här artikeln.

Några av exemplen i denna handledning inkluderar en XML-sträng. Istället för att upprepa det i varje exempel, lägg den raden i en fil, som du inkluderar i varje exempel. Denna linje visas i följande exempel. Dessutom kan du skapa ett XML-dokument och läsa det med funktionen simplexml_load_file ().

Exempel # 1 Exempel.php-fil med XML-sträng

$ xmlstr =<<


PHP: Introduktion av Parser


Fröken. Kodare
Onlivia Actora


Herr. Kodare
El ActÓr


Så det är ett språk. Det är fortfarande ett programmeringsspråk. Eller
är det ett skriptspråk? Allt avslöjas i denna dokumentär
som en skräckfilm.




7
5


XML;
?>

SimpleXML är lätt att använda! Försök att få någon sträng eller nummer från det underliggande XML-dokumentet.

Exempel # 2 Hämta en del av ett dokument

inkludera "example.php";

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

Så det är ett språk. Det är fortfarande ett programmeringsspråk. Eller är det ett skriptspråk? Allt avslöjas i denna skräckliknande dokumentär.

I PHP kan du komma åt ett element i ett XML-dokument som innehåller ogiltiga tecken (t.ex. ett bindestreck) i sitt namn genom att omsluta det givna elementnamnet i klammerparenteser och apostrofer.

Exempel # 3 Hämta en sträng

inkludera "example.php";

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

Resultatet av detta exempel:

PHP löser alla mina webbproblem

Exempel # 4 Åtkomst till icke-unika element i SimpleXML

I händelse av att det finns flera instanser av underordnade element i ett överordnat element, måste du använda standard iterationsmetoderna.

inkludera "example.php";

$ filmer = nytt SimpleXMLElement ($ xmlstr);

/ * För varje nod , kommer vi att visa namnet separat . */
foreach ($ filmer -> film -> karaktärer -> karaktär som $ karaktär) (
echo $ karaktär -> namn, "spelande", $ karaktär -> skådespelare, PHP_EOL;
}

?>

Resultatet av detta exempel:

Fröken. Coder spelad av Onlivia Actora Mr. Coder spelad av El Actór

Kommentar:

Egenskaper ( $ filmer-> film i föregående exempel) är inte matriser. Det är en iterabel som en array.

Exempel # 5 Använda attribut

Fram till nu har vi bara fått namn och värden på elementen. SimpleXML kan också komma åt attributen för ett element. Ett elementattribut kan nås på samma sätt som arrayelement ( array).

inkludera "example.php";

$ filmer = nytt SimpleXMLElement ($ xmlstr);

/ * Åtkomst till noden den första filmen.
* Vi kommer också att visa betygsskalan. * /
foreach ($ filmer -> film [0] -> betyg som $ betyg) (
switch ((sträng) $ rating ["typ"]) ( // Hämta elementets attribut efter index
case "tummen":
echo $-betyg, "tummen upp";
ha sönder;
fallet "stjärnor":
echo $ rating, "stjärnor";
ha sönder;
}
}
?>

Resultatet av detta exempel:

7 tummen upp5 stjärnor

Exempel # 6 Jämföra element och attribut med text

För att jämföra ett element eller attribut med en sträng, eller för att skicka det till en funktion som text, måste du casta det till en sträng med (sträng)... Annars kommer PHP att behandla elementet som ett objekt.

inkludera "example.php";

$ filmer = nytt SimpleXMLElement ($ xmlstr);

if ((sträng) $ filmer -> film -> titel == "PHP: The Rise of the Parser") {
skriva ut "Min favoritfilm.";
}

echo htmlentities ((sträng) $ filmer -> film -> titel);
?>

Resultatet av detta exempel:

Min favoritfilm Php: The Emergence of the Parser

Exempel # 7 Jämföra två objekt

Två SimpleXMLElement anses olika även om de pekar på samma objekt sedan PHP 5.2.0.

inkludera "example.php";

$ movies1 = nytt SimpleXMLElement ($ xmlstr);
$ movies2 = nytt SimpleXMLElement ($ xmlstr);
var_dump ($ filmer1 == $ filmer2); // false sedan PHP 5.2.0
?>

Resultatet av detta exempel:

Exempel # 8 Använda XPath

SimpleXML inkluderar inbyggt XPath-stöd. Hitta alla föremål :

inkludera "example.php";

$ filmer = nytt SimpleXMLElement ($ xmlstr);

foreach ($ filmer -> xpath ("// karaktär") som $ tecken) (
echo $ karaktär -> namn, "spelande", $ karaktär -> skådespelare, PHP_EOL;
}
?>

"// "fungerar som en mall. För att ange en absolut sökväg, utelämna ett av snedstrecket.

Resultatet av detta exempel:

Fröken. Coder spelad av Onlivia Actora Mr. Coder spelad av El Actór

Exempel # 9 Inställningsvärden

Data i SimpleXML behöver inte vara oföränderlig. Objektet låter dig manipulera alla element.

inkludera "example.php";
$ filmer = nytt SimpleXMLElement ($ xmlstr);

$ filmer -> film [0] -> tecken -> karaktär [0] -> namn = "Fröken Coder";

echo $ filmer -> asXML ();
?>

Resultatet av detta exempel:

PHP: Introduktion av Parser Fröken kodare Onlivia Actora Herr. Kodare El ActÓr 7 5

Exempel # 10 Lägga till element och attribut

Sedan PHP 5.1.3 har SimpleXML möjligheten att enkelt lägga till underordnade element och attribut.

inkludera "example.php";
$ filmer = nytt SimpleXMLElement ($ xmlstr);

$ karaktär = $ filmer -> film [0] -> karaktärer -> addChild ("karaktär");
$ tecken -> addChild ("namn", "Mr. Parser");
$ karaktär -> addChild ("skådespelare", "John Doe");

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

echo $ filmer -> asXML ();
?>

Resultatet av detta exempel:

PHP: Introduktion av Parser Fröken. Kodare Onlivia Actora Herr. Kodare El ActÓr Herr. ParserJohn Doe Så det är ett språk. Det är fortfarande ett programmeringsspråk. Eller är det ett skriptspråk? Allt avslöjas i denna skräckliknande dokumentär. PHP löser alla mina webbuppgifter 7 5 PG

Exempel # 11 Interagera med DOM

PHP kan konvertera XML-noder från SimpleXML till DOM-format och vice versa. Det här exemplet visar hur du kan ändra ett DOM-element i SimpleXML.

$ dom = nytt DOMDocument;
$ dom -> loadXML ( "dumheter" );
om (! $ dom) (
eko "Ett fel uppstod när dokumentet analyserades";
utgång;
}

$ böcker = simplexml_import_dom ($ dom);

echo $ böcker -> bok [0] -> titel;
?>

Resultatet av detta exempel:

4 år sedan

Det finns ett vanligt "trick" som ofta föreslagits för att konvertera ett SimpleXML-objekt till en array, genom att köra det genom json_encode () och sedan json_decode (). Jag skulle vilja förklara varför detta är en dålig idé.

Helt enkelt för att hela poängen med SimpleXML är att vara enklare att använda och kraftfullare än en vanlig array. Du kan till exempel skrivabar -> baz ["bing"]?> och det betyder samma sak sombar [0] -> baz [0] ["bing"]?>, oavsett hur många bar eller baz-element det finns i XML; och om du skriverbar [0] -> baz [0]?> får du allt stränginnehåll i den noden - inklusive CDATA-sektioner - oavsett om den också har underordnade element eller attribut. Du har också tillgång till namnutrymmesinformation, möjligheten att göra enkla redigeringar av XML, och till och med möjligheten att "importera" till ett DOM-objekt, för mycket mer kraftfull manipulation. Allt detta går förlorat genom att förvandla objektet till en array istället för att läsa och förstå exemplen på den här sidan.

Dessutom, eftersom den inte är designad för detta ändamål, kommer konverteringen till JSON och tillbaka faktiskt att förlora information i vissa situationer. Till exempel kommer alla element eller attribut i ett namnområde helt enkelt att kasseras, och allt textinnehåll kommer att kasseras om ett element också har underordnade eller attribut. Ibland kommer det här "inte att spela någon roll, men om du får för vana att konvertera allt till arrayer" kommer det att svida dig så småningom.

Naturligtvis kan du skriva en smartare konvertering, som inte hade dessa begränsningar, men vid den tidpunkten får du inget värde av SimpleXML alls, och du borde bara använda XML Parser-funktionerna på lägre nivå, eller XMLReader-klassen, för att skapa din struktur. Du kommer fortfarande "inte att ha den extra bekvämlighetsfunktionaliteten hos SimpleXML, men det" är din förlust.

2 år sedan

Om din xml-sträng innehåller booleaner kodade med "0" och "1", kommer du att stöta på problem när du castar elementet direkt till bool:

$ xmlstr =<<

1
0

XML;
$ värden = nytt SimpleXMLElement ($ xmlstr);
$ truevalue = (bool) $ values-> truevalue; // Sann
$ falsevalue = (bool) $ values-> falsevalue; // också sant!!!

Istället måste du kasta till sträng eller int först:

$ truevalue = (bool) (int) $ values-> truevalue; // Sann
$ falsevalue = (bool) (int) $ values-> falsevalue; // falskt

9 år sedan

Om du behöver mata ut giltig xml i ditt svar, glöm inte att ställa in din rubrikinnehållstyp till xml förutom att eko ut resultatet av asXML ():

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

// mata ut xml i ditt svar:
header ("Innehållstyp: text / xml");
echo $ xml -> asXML ();
?>

9 år sedan

Från README-filen:

SimpleXML är tänkt att vara ett enkelt sätt att komma åt XML-data.

SimpleXML-objekt följer fyra grundläggande regler:

1) egenskaper betecknar element-iteratorer
2) numeriska index betecknar element
3) icke-numeriska index anger attribut
4) strängkonvertering gör det möjligt att komma åt TEXT-data

Vid iteration av egenskaper upprepas alltid tillägget
alla noder med det elementnamnet. Således metod barn () måste vara
kallas att iterera över subnoder. Men gör också följande:
foreach ($ obj-> nodnamn som $ elem) (
// gör något med $ elem
}
resulterar alltid i iteration av "nodnamn"-element. Så inget vidare
kontroll behövs för att särskilja antalet noder av den typen.

När ett element TEXT-data nås via en egenskap
då inkluderar resultatet inte TEXT-data för underelement.

Kända problem
============

På grund av motorproblem är det för närvarande inte möjligt att komma åt
ett underelement av index 0: $ objekt-> egenskap.

8 år sedan

Att använda saker som: is_object ($ xml-> modul-> admin) för att kontrollera om det faktiskt finns en nod som heter "admin", verkar "inte fungera som förväntat, eftersom simplexml alltid returnerar ett objekt - i så fall ett tomt sådant - även om en viss nod inte finns.
För mig verkar den gamla goda funktionen tomma () fungera alldeles utmärkt i sådana fall.

8 år sedan

Ett snabbt tips om xpath-frågor och standardnamnrymder. Det ser ut som att XML-systemet bakom SimpleXML fungerar på samma sätt som jag tror att XML-systemet .NET använder: när man behöver adressera något i standardnamnutrymmet måste man deklarera namnområdet med registerXPathNamespace och sedan använda dess prefix till adressera annars i standardnamnområdet levande element.

$ sträng =<<

Fyrtio Vad?
Joe
Jane

Jag vet att det "är svaret - men vad" är frågan?


XML;

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

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

?>

9 år sedan

Även om SimpleXMLElement påstår sig vara iterabel, verkar det inte implementera standard Iterator-gränssnittsfunktioner som :: nästa och :: återställs korrekt. Därför verkar medan foreach () fungerar, fungerar som nästa (), aktuell () eller varje () inte fungera som du förväntar dig - pekaren verkar aldrig röra sig eller återställs hela tiden.

6 år sedan

Om kodningen av XML-dokumentet skiljer sig från UTF-8, måste kodningsdeklarationen följa omedelbart efter version = "..." och före fristående = "...". Detta är ett krav i XML-standarden.

Om kodning av XML-dokument skiljer sig från UTF-8. Kodningsdeklarationen bör följa omedelbart efter versionen = "..." och före fristående = "...". Detta krav är standard XML.


Ok

Ryska språket. ryska språket
Allvarligt fel: Oupptäckt undantag "Undantag" med meddelandet "Sträng kunde inte tolkas som XML" i ...

Att analysera XML innebär i huvudsak att gå igenom ett XML-dokument och returnera lämplig data. Medan ett ökande antal webbtjänster returnerar data i JSON-format använder de flesta fortfarande XML, så det är viktigt att behärska XML-parsning om du vill använda hela utbudet av tillgängliga API:er.

Använder tillägget SimpleXML i PHP, som lades till i PHP 5.0, är ​​det mycket enkelt och okomplicerat att arbeta med XML. I den här artikeln kommer jag att visa dig hur du gör detta.

Grunderna för användning

Låt oss börja med följande exempel languages.xml:


>

> 1972>
> Dennis ritchie >
>

> 1995>
> Rasmus Lerdorf >
>

> 1995>
> James gosling >
>
>

Detta XML-dokument innehåller en lista över programmeringsspråk med viss information om varje språk: året för dess implementering och namnet på dess skapare.

Det första steget är att ladda XML med hjälp av funktioner antingen simplexml_load_file () eller simplexml_load_string ()... Som namnet på funktionerna antyder kommer den förra att ladda XML från en fil och den senare kommer att ladda XML från en sträng.

Båda funktionerna läser in hela DOM-trädet i minnet och returnerar ett objekt EnkelXMLElement... I exemplet ovan lagras objektet i variabeln $ languages. Du kan använda funktioner var_dump () eller print_r () för att få information om det returnerade objektet, om du vill.

SimpleXMLElement-objekt
[lang] => Array
[0] => SimpleXMLElement-objekt
[@ attribut] => Array
[namn] => C
[uppträdde] => 1972
[skapare] => Dennis Ritchie
[1] => SimpleXMLElement-objekt
[@ attribut] => Array
[namn] => PHP
[uppträdde] => 1995
[skapare] => Rasmus Lerdorf
[2] => SimpleXMLElement-objekt
[@ attribut] => Array
[namn] => Java
[uppträdde] => 1995
[skapare] => James Gosling
)
)

Denna XML innehåller rotelementet språk, inuti vilken det finns tre element lang. Varje element i arrayen motsvarar ett element lang i XML-dokumentet.

Du kan komma åt egenskaperna för ett objekt med operatorn -> ... Till exempel kommer $ languages-> lang att returnera ett SimpleXMLElement-objekt som matchar det första elementet lang... Detta objekt innehåller två egenskaper: dök upp och skapare.

$ språk -> lang [0] -> dök upp;
$ languages ​​-> lang [0] -> skapare;

Det är väldigt enkelt att visa en lista över språk och visa deras egenskaper med hjälp av en standardloop som t.ex för varje.

foreach ($ språk -> lang som $ lang) (
printf (
"" ,
$ lang ["namn"],
$ lang -> dök upp,
$ lang -> skapare
) ;
}

Lägg märke till hur jag fick åtkomst till attributnamnet för lang-elementet för att få språknamnet. På så sätt kan du komma åt alla attribut för ett element som representeras som ett SimpleXMLElement-objekt.

Arbeta med namnutrymmen

När du arbetar med olika webbtjänsters XML kommer du att stöta på elementnamnutrymmen mer än en gång. Låt oss ändra vår languages.xml för att visa ett exempel på användning av namnutrymmet:



xmlns: dc =>

> 1972>
> Dennis ritchie >
>

> 1995>
> Rasmus Lerdorf >
>

> 1995>
> James gosling >
>
>

Nu elementet skapare placeras i namnutrymmet dc som pekar på http://purl.org/dc/elements/1.1/. Om du försöker skriva ut språkskaparna med vår tidigare kod kommer det inte att fungera. För att kunna läsa namnrymden för element måste du använda något av följande tillvägagångssätt.

Det första tillvägagångssättet är att använda URI:er direkt i kod när man refererar till elementets namnområde. Följande exempel visar hur detta går till:

$ dc = $ språk -> lang [1] -> barn ( "http://purl.org/dc/elements/1.1/") ;
echo $ dc -> skapare;

Metod barn () tar ett namnutrymme och returnerar underordnade element som börjar med ett prefix. Det krävs två argument, det första är ett XML-namnområde och det andra valfria argumentet som är standard falsk... Om det andra argumentet är TRUE kommer namnområdet att behandlas som ett prefix. Om FALSE kommer namnområdet att behandlas som ett URL-namnområde.

Det andra tillvägagångssättet är att läsa URI-namnen från dokumentet och använda dem när du hänvisar till elementnamnområdet. Detta är faktiskt det bästa sättet att komma åt elementen eftersom du inte behöver hårdkoda URI:n.

$ namnutrymmen = $ språk -> getNamespaces (true);
$ dc = $ språk -> lang [1] -> barn ($ namnrymder ["dc"]);

echo $ dc -> skapare;

Metod GetNamespaces () returnerar en uppsättning prefixnamn och deras associerade URI:er. Det krävs en extra parameter, vilket som standard är falsk... Om du ställer in det som Sann då kommer den här metoden att returnera namnen som används i föräldra- och undernoderna. Annars hittar den namnutrymmen som endast används i den överordnade noden.

Du kan nu gå igenom listan över språk enligt följande:

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

foreach ($ språk -> lang som $ lang) (
$ dc = $ lang -> barn ($ ns ["dc"]);
printf (
"

% s dök upp i % d och skapades av % s.

" ,
$ lang ["namn"],
$ lang -> dök upp,
$ dc -> skapare
) ;
}

Fallstudie – Analysera en YouTube-videokanal

Låt oss ta en titt på ett exempel som tar emot ett RSS-flöde från en YouTube-kanal och visar länkar till alla videor från den. För att göra detta måste du kontakta följande adress:

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

URL:en returnerar en lista över de senaste videorna från den givna kanalen i XML-format. Vi analyserar XML och får följande information för varje video:

  • Länk till video
  • Miniatyr
  • namn

Vi börjar med att hitta och ladda XML:en:

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

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

Om du tittar på XML-flödet kan du se att det finns flera element där entitet, som var och en lagrar detaljerad information om en specifik video från en kanal. Men vi använder bara miniatyrer, video-url och titel. Dessa tre element är ättlingar till elementet grupp som i sin tur är ett barn till inträde:

>

>



Titel... >

>

>

Vi ska bara gå igenom alla element. inträde, och för var och en av dem extraherar vi nödvändig information. anteckna det spelare, Miniatyr och titel finns i medianamnutrymmet. Därför måste vi fortsätta som i föregående exempel. Vi hämtar namnen från dokumentet och använder namnutrymmet när vi hänvisar till elementen.

foreach ($ feed -> entry som $ entry) (
$ group = $ entry -> barn ($ ns ["media"]);
$ grupp = $ grupp -> grupp;
$ thumbnail_attrs = $ group -> thumbnail [1] -> attribut ();
$ image = $ thumbnail_attrs ["url"];
$ spelare = $ grupp -> spelare -> attribut ();
$ länk = $ spelare ["url"];
$ titel = $ grupp -> titel;
printf ( "

" ,
$ spelare, $ bild, $ titel);
}

Slutsats

Nu när du vet hur man använder SimpleXML för att analysera XML-data kan du förbättra dina färdigheter genom att analysera olika XML-flöden med olika API:er. Men det är viktigt att komma ihåg att SimpleXML läser in hela DOM i minnet, så om du analyserar en stor datauppsättning kan du få slut på minne. Läs dokumentationen för att lära dig mer om SimpleXML.


Om du har några frågor rekommenderar vi att du använder vår

Nu ska vi studera att arbeta med XML. XML är ett format för utbyte av data mellan webbplatser. Det är väldigt likt HTML, förutom att XML tillåter sina egna taggar och attribut.

Varför behöver du XML när du analyserar? Ibland händer det att sajten som du behöver analysera har ett API med vilket du kan få vad du vill utan alltför mycket påfrestningar. Därför bara ett tips - innan du analyserar webbplatsen, kontrollera om den har ett API.

Vad är ett API? Detta är en uppsättning funktioner med vilka du kan skicka en förfrågan till denna webbplats och få önskat svar. Detta svar kommer oftast i XML-format. Så låt oss börja studera det.

Arbeta med XML i PHP

Anta att du har XML. Det kan vara i en sträng, eller lagras i en fil, eller returneras på begäran till en specifik URL.

Låt XML lagras i en sträng. I det här fallet, från den här raden måste du skapa ett objekt med hjälp av nytt SimpleXMLElement:

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

Nu har vi en variabel $ xml ett objekt med analyserad XML lagras. Genom att komma åt egenskaperna för detta objekt kan du komma åt innehållet i XML-taggarna. Hur exakt - vi kommer att analysera lite nedan.

Om XML lagras i en fil eller returneras genom att komma åt en URL (vilket oftast är fallet), bör du använda funktionen simplexml_load_file som gör samma föremål $ xml:

Kolya 25 1000

$ xml = simplexml_load_file (sökväg till fil eller url);

Hur man arbetar

I exemplen nedan lagras vår XML i en fil eller URL.

Låt följande XML ges:

Kolya 25 1000

Låt oss få den anställdes namn, ålder och lön:

$ xml = simplexml_load_file (sökväg till fil eller url); echo $ xml-> namn; // skriver ut "Kolya" echo $ xml-> age; // skriver ut 25 echo $ xml-> lön; // kommer att skriva ut 1000

Som du kan se har $ xml-objektet egenskaper som motsvarar taggarna.

Du kanske har märkt att taggen visas inte någonstans i adressen. Detta beror på att det är root-taggen. Du kan till exempel byta namn på den till - och ingenting kommer att förändras:

Kolya 25 1000

$ xml = simplexml_load_file (sökväg till fil eller url); echo $ xml-> namn; // skriver ut "Kolya" echo $ xml-> age; // skriver ut 25 echo $ xml-> lön; // kommer att skriva ut 1000

Det kan bara finnas en rottagg i XML, precis som en tagg i normal HTML.

Låt oss modifiera vår XML lite:

Kolya 25 1000

I det här fallet kommer vi att få en kedja av samtal:

$ xml = simplexml_load_file (sökväg till fil eller url); echo $ xml-> arbetare-> namn; // skriver ut "Kolya" echo $ xml-> worker-> age; // skriver ut 25 echo $ xml-> arbetare-> lön; // kommer att skriva ut 1000

Arbeta med attribut

Låt vissa data lagras i attribut:

Nummer ett

$ xml = simplexml_load_file (sökväg till fil eller url); echo $ xml-> worker ["namn"]; // visar "Kolya" echo $ xml-> worker ["ålder"]; // skriver ut 25 echo $ xml-> arbetare ["lön"]; // skriver ut 1000 echo $ xml-> worker; // visar "Nummer 1"

Avstavningstaggar

Taggar (och attribut) med bindestreck är tillåtna i XML. I det här fallet nås sådana taggar så här:

Kolya Ivanov

$ xml = simplexml_load_file (sökväg till fil eller url); echo $ xml-> worker -> (förnamn); // skriver ut "Kolya" echo $ xml-> worker -> (efternamn); // visar "Ivanov"

Iteration över en slinga

Låt nu vi inte ha en anställd, utan flera. I det här fallet kan vi iterera över vårt objekt med hjälp av en foreach loop:

Kolya 25 1000 Vasya 26 2000 Peter 27 3000

$ xml = simplexml_load_file (sökväg till fil eller url); foreach ($ xml som $ worker) (echo $ worker-> name; // skriver ut "Kolya", "Vasya", "Petya")

Från objekt till normal array

Om du inte är bekväm med att arbeta med ett objekt kan du konvertera det till en normal PHP-array med följande smarta trick:

$ xml = simplexml_load_file (sökväg till fil eller url); var_dump (json_decode (json_encode ($ xml), true));

Mer information

Parsning baserat på sitemap.xml

Ofta har webbplatsen en sitemap.xml-fil. Den här filen lagrar länkar till alla sidor på webbplatsen för att underlätta indexering av dem av sökmotorer (indexering är i själva verket tolkningen av webbplatsen av Yandex och Google).

I allmänhet bör vi inte bry oss mycket om varför den här filen behövs, huvudsaken är att om den finns kan du inte klättra på sidorna på webbplatsen med några smarta metoder, utan helt enkelt använda den här filen.

Så här kontrollerar du närvaron av den här filen: låt oss analysera webbplatsen site.ru och gå sedan till site.ru/sitemap.xml i webbläsaren - om du ser något så finns det där och om du inte ser det , då tyvärr.

Om det finns en webbplatskarta innehåller den länkar till alla sidor på webbplatsen i XML-format. Ta lugnt denna XML, analysera den, separata länkar till sidorna du behöver på något sätt som är bekvämt för dig (till exempel genom att analysera URL:en, som beskrevs i spindelmetoden).

Som ett resultat får du en lista med länkar för att analysera, du behöver bara gå till dem och analysera innehållet du behöver.

Läs mer om enheten sitemap.xml i Wikipedia.

Vad göra här näst:

Börja lösa problem på följande länk: uppgifter för lektionen.

När du har bestämt allt, gå vidare till att studera ett nytt ämne.







2021 gtavrl.ru.