Pato la php la kichanganuzi cha Xml kwenye jedwali. Vichanganuzi vya XML vinatumika kwa nini na vinawezaje kuwa muhimu? SAX katika hatua

Katika makala ya mwisho wewe na mimi, na niliahidi kwamba katika makala inayofuata wewe na mimi tutaifafanua. Na leo nitakuonyesha jinsi unaweza chunguza hati ya XML katika PHP.

Ninapendekeza kuchanganua hati tuliyounda katika kifungu kilichopita, na kutoa data kutoka hapo hadi kwa kivinjari. Hapa kuna nambari ya maandishi:

$dom = new domDocument("1.0", "utf-8"); // Unda toleo la hati ya XML 1.0 na usimbuaji wa utf-8
$dom->load("users.xml"); // Pakia hati ya XML kutoka faili hadi kitu cha DOM
$mizizi = $dom->documentElement; // Pata kipengele cha mizizi
$ watoto = $mizizi->childNodes; // Pata watoto wa kipengele cha mizizi
/* Pindua kupitia vitu vilivyopokelewa */
kwa ($i = 0; $i< $childs->urefu; $i++) (
$mtumiaji = $childs->kipengee($i); // Pata kipengee kifuatacho kutoka kwa NodeList
$lp = $user->childNodes; // Pata watoto wa node ya "mtumiaji".
$id = $user->getAttribute("id"); // Pata thamani ya sifa ya "id" ya nodi ya "mtumiaji".
$login = $lp->item(0)->nodeValue; // Pata thamani ya nodi ya "kuingia".
$password = $lp->kipengee(1)->nodeValue; // Pata thamani ya nodi ya "nenosiri".
/* Toa data iliyopokelewa */
echo "ID: $id
";
echo "Ingia: $ ingia
";
echo "Nenosiri: $password
";
mwangwi "-----------------------
";
}
?>

Kutoka kwa nambari hii haifai kuelewa tu jinsi ya kuchanganua hati ya XML katika PHP, lakini pia kwamba yeye mchakato wa kuchanganua unategemea muundo wa hati. Hiyo ni, lazima ujue muundo ni nini, vinginevyo kuchanganua hati kama hiyo itakuwa shida. Tayari niliandika mara moja kwamba kuu kipengele cha XML ni ukali wa sintaksia. Natumaini sasa umeelewa kwa nini hii ni muhimu sana. Bila hii ugumu wa kanuni"Itakuwa vigumu sana kuchanganua hati, na jambo hili linahitajika mara nyingi sana. Msingi wakati wa kuagiza data kutoka Faili ya XML na kisha kuziweka kwenye hifadhidata.


uchapishaji wa makala hii inaruhusiwa tu na kiungo kwa tovuti ya mwandishi wa makala

Katika makala hii nitaonyesha mfano wa jinsi ya kuchanganua faili kubwa ya XML. Ikiwa seva yako (mwenyeji) haizuii kuongeza muda wa hati, basi unaweza kuchanganua faili ya XML yenye uzito wa angalau gigabaiti; mimi binafsi nilichanganua faili kutoka kwa ozoni yenye uzito wa megabaiti 450.

Wakati wa kuchanganua faili kubwa za XML, shida mbili huibuka:
1. Kumbukumbu haitoshi.
2. Hakuna muda wa kutosha uliotengwa kwa hati kufanya kazi.

Tatizo la pili na wakati linaweza kutatuliwa ikiwa seva haikatazi.
Lakini shida na kumbukumbu ni ngumu kusuluhisha, hata ikiwa tunazungumza juu ya seva yako mwenyewe, basi kusonga faili za megabytes 500 sio rahisi sana, na haiwezekani kuongeza kumbukumbu kwenye mwenyeji na VDS.

PHP ina chaguzi kadhaa za usindikaji za XML zilizojengwa - SimpleXML, DOM, SAX.
Chaguzi hizi zote zimeelezewa kwa kina katika vifungu vingi vilivyo na mifano, lakini mifano yote inaonyesha kufanya kazi na hati kamili ya XML.

Hapa kuna mfano mmoja, kupata kitu kutoka kwa faili ya XML

Sasa unaweza kusindika kitu hiki, LAKINI...
Kama unaweza kuona, faili nzima ya XML inasomwa kwenye kumbukumbu, kisha kila kitu kinachanganuliwa kuwa kitu.
Hiyo ni, data zote huenda kwenye kumbukumbu na ikiwa hakuna kumbukumbu ya kutosha iliyotengwa, hati itaacha.

Chaguo hili halifai kwa usindikaji faili kubwa; unahitaji kusoma mstari wa faili kwa mstari na kuchakata data hii moja baada ya nyingine.
Katika kesi hii, ukaguzi wa uhalali pia unafanywa wakati data inachakatwa, kwa hivyo unahitaji kuwa na uwezo wa kurudisha nyuma, kwa mfano, kufuta data yote iliyoingizwa kwenye hifadhidata ikiwa ni faili batili ya XML, au kutekeleza kupita mbili. kupitia faili, soma kwanza kwa uhalali, kisha usome kwa usindikaji wa data.

Hapa kuna mfano wa kinadharia wa kuchanganua faili kubwa ya XML.
Hati hii husoma herufi moja kwa wakati kutoka kwa faili, hukusanya data hii katika vizuizi na kuituma kwa kichanganuzi cha XML.
Njia hii inasuluhisha kabisa shida ya kumbukumbu na haina kusababisha mzigo, lakini inazidisha shida kwa wakati. Jinsi ya kujaribu kutatua tatizo kwa muda, soma hapa chini.

Kazi webi_xml ($faili)
{

########
### kipengele cha data

{
chapisha data ya $;
}
############################################



{
chapisha $name ;
print_r($ atts);
}


## kufunga tagi
kipengele endElement ($parser, $name)
{
chapisha $name ;
}
############################################

($xml_parser, "data");

// fungua faili
$fp = fopen($file, "r");

$perviy_vxod = 1; $data = "" ;



{

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


if($simvol != ">" ) (endelea;)


mwangwi"

mapumziko;
}

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

Webi_xml("1.xml");

?>

Katika mfano huu, ninaweka kila kitu kwenye kazi moja webi_xml() na chini kabisa unaweza kuona simu yake.
Hati yenyewe ina kazi kuu tatu:
1. Chaguo la kukokotoa ambalo linashika ufunguzi wa lebo ya startElement()
2. Chaguo za kukokotoa ambazo hunasa lebo ya kufunga ya EndElement().
3. Na data ya kupokea data ya kazi () .

Hebu tuchukulie kuwa yaliyomo kwenye faili 1.xml ni kichocheo



< title >Mkate rahisi
< ingredient amount = "3" unit = "стакан" >Unga
< ingredient amount = "0.25" unit = "грамм" >Chachu
< ingredient amount = "1.5" unit = "стакан" >Maji ya joto
< ingredient amount = "1" unit = "чайная ложка" >Chumvi
< instructions >
< step > Changanya viungo vyote na ukanda vizuri.
< step > Funika kwa kitambaa na uondoke kwa saa moja kwenye chumba cha joto..
< step > Kanda tena, weka kwenye karatasi ya kuoka na uweke kwenye oveni.
< step > Tembelea tovuti


Tunaanza kila kitu kwa kupiga kazi ya jumla webi_xml ("1.xml" );
Ifuatayo, kichanganuzi kinaanza katika chaguo la kukokotoa na kubadilisha majina ya lebo zote kuwa herufi kubwa ili lebo zote ziwe na hali sawa.

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

Sasa tunaonyesha ni kazi zipi zitafanya kazi ili kupata ufunguzi wa lebo, kufunga na usindikaji wa data

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

Ifuatayo inakuja ufunguzi wa faili iliyoainishwa, ikirudia kupitia faili herufi moja kwa wakati mmoja na kila herufi inaongezwa kwa utaftaji wa kamba hadi mhusika apatikane. > .
Ikiwa hii ndiyo ufikiaji wa kwanza wa faili, basi njiani kila kitu kisichohitajika mwanzoni mwa faili kitafutwa, kila kitu kinachokuja hapo awali. , hii ndio lebo ambayo XML inapaswa kuanza nayo.
Kwa mara ya kwanza, kutofautiana kwa kamba kutakuwa na kamba

Na kutuma kwa disassembler
xml_parse ($xml_parser, $data, feof ($fp));
Baada ya kuchakata data, utofauti wa kamba huwekwa upya na mkusanyiko wa data kwenye kamba huanza tena na kamba huundwa kwa mara ya pili.

Juu ya tatu
</b><br>ya nne <br><b>Mkate rahisi

Tafadhali kumbuka kuwa utaftaji wa safu hutengenezwa kila wakati kutoka kwa lebo iliyokamilishwa > na si lazima kutuma burglar tag wazi na kufungwa na data, kwa mfano
Mkate rahisi
Ni muhimu kwa mhudumu huyu kupokea lebo nzima isiyovunjika, angalau tag moja wazi, na katika hatua inayofuata tag iliyofungwa, au mara moja kupokea mistari 1000 ya faili, haijalishi, jambo kuu ni kwamba tag. haina kuvunja, kwa mfano

le>mkate wa kawaida
Kwa njia hii, haiwezekani kutuma data kwa kidhibiti, kwani tepe imepasuka.
Unaweza kuja na njia yako mwenyewe ya kutuma data kwa kidhibiti, kwa mfano, kukusanya megabyte 1 ya data na kuituma kwa kidhibiti ili kuongeza kasi, hakikisha tu kuwa vitambulisho vimekamilika kila wakati na data inaweza kuchanika.
Rahisi</b><br><b>mkate

Kwa hivyo, katika sehemu unavyotaka, unaweza kutuma faili kubwa kwa processor.

Sasa hebu tuangalie jinsi data hii inavyochakatwa na jinsi ya kuipata.

Wacha tuanze na kazi ya vitambulisho vya ufunguzi startElement ($parser, $name, $attrs)
Wacha tuchukue kuwa usindikaji umefikia mstari
< ingredient amount = "3" unit = "стакан" >Unga
Kisha ndani ya kazi kutofautisha $name itakuwa sawa na kiungo yaani, jina la tag iliyofunguliwa (haijaja kufunga lebo bado).
Pia katika kesi hii, safu ya sifa za lebo hii $attrs itapatikana, ambayo itakuwa na data. kiasi = "3" na kitengo = "glasi".

Baada ya hayo, data ya lebo wazi ilichakatwa na kazi data ($parser, $data)
Tofauti ya data ya $ itakuwa na kila kitu kilicho kati ya vitambulisho vya kufungua na kufunga, kwa upande wetu hii ni maandishi Muka

Na usindikaji wa kamba yetu kwa kazi huisha endElement ($parser, $name)
Hili ndilo jina la lebo iliyofungwa, kwa upande wetu $name itakuwa sawa na kiungo

Na baada ya hapo kila kitu kilikwenda kwenye miduara tena.

Mfano hapo juu unaonyesha tu kanuni ya usindikaji wa XML, lakini kwa matumizi halisi inahitaji kurekebishwa.
Kwa kawaida, inabidi uchanganue XML kubwa ili kuingiza data kwenye hifadhidata, na kuchakata data ipasavyo unahitaji kujua ni lebo gani iliyo wazi ambayo data ni ya, ni kiwango gani cha kuweka lebo na ni lebo zipi zimefunguliwa katika safu ya juu. Kwa habari hii, unaweza kusindika faili kwa usahihi bila matatizo yoyote.
Ili kufanya hivyo, unahitaji kuanzisha vigezo kadhaa vya kimataifa ambavyo vitakusanya taarifa kuhusu vitambulisho vilivyo wazi, nesting na data.
Hapa kuna mfano unaweza kutumia

Kazi webi_xml ($faili)
{
kimataifa $webi_depth ; // counter kufuatilia kina cha kiota
$webi_depth = 0;
kimataifa $webi_tag_open ; // itakuwa na safu ya lebo zilizofunguliwa kwa sasa
$webi_tag_open = safu();
kimataifa $webi_data_temp ; // safu hii itakuwa na data ya lebo moja

####################################################
### kipengele cha data
data ya kazi ($parser, $data)
{
kimataifa $webi_depth ;
kimataifa $webi_tag_open ;
kimataifa $webi_data_temp ;
// ongeza data kwenye safu inayoonyesha kuweka kiota na lebo iliyofunguliwa kwa sasa
$webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "data" ].= $data ;
}
############################################

####################################################
### kufungua tagi chaguo
kazi startElement ($parser, $name, $attrs)
{
kimataifa $webi_depth ;
kimataifa $webi_tag_open ;
kimataifa $webi_data_temp ;

// ikiwa kiwango cha kuota si sifuri tena, basi lebo moja tayari imefunguliwa
// na data kutoka kwake tayari iko kwenye safu, unaweza kuichakata
ikiwa ($webi_depth)
{




" ;

chapa"
" ;
print_r($webi_tag_open); // safu ya vitambulisho wazi
chapa"


" ;

// baada ya kusindika data, ifute ili kufungua kumbukumbu
unset($GLOBALS [ "webi_data_temp" ][ $webi_depth ]);
}

// sasa lebo inayofuata inafunguliwa na usindikaji zaidi utafanyika katika hatua inayofuata
$webi_dep++; // kuongeza kiota

$webi_tag_open [ $webi_depth ]= $name ; // ongeza lebo wazi kwa safu ya habari
$webi_data_temp [ $webi_depth ][ $name ][ "attrs" ]= $attrs ; // sasa ongeza sifa za lebo

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

#################################################
## kufunga tagi
kipengele endElement ($parser, $name) (
kimataifa $webi_depth ;
kimataifa $webi_tag_open ;
kimataifa $webi_data_temp ;

// usindikaji wa data huanza hapa, kwa mfano kuongeza kwenye hifadhidata, kuhifadhi kwenye faili, nk.
// $webi_tag_open ina msururu wa lebo wazi kulingana na kiwango cha nesting
// kwa mfano $webi_tag_open[$webi_depth] ina jina la tagi iliyofunguliwa ambayo maelezo yake yanachakatwa kwa sasa
// kiwango cha kuweka lebo ya $webi_depth
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["attrs"] safu ya sifa za lebo
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["data"] tagi data

Chapisha "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" ]);
chapa"
" ;
print_r($webi_tag_open);
chapa"


" ;

Haijawekwa($GLOBALS [ "webi_data_temp" ]); // baada ya kusindika data, tunafuta safu nzima na data, kwani lebo ilifungwa
unset($GLOBALS [ "webi_tag_open" ][ $webi_depth ]); // futa maelezo kuhusu lebo hii iliyofunguliwa... tangu ilipofungwa

$webi_depth --; // kupunguza kutaga
}
############################################

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

// onyesha ni kazi gani zitafanya kazi wakati wa kufungua na kufunga vitambulisho
xml_set_element_handler($xml_parser, "startElement", "endElement");

// taja kazi ya kufanya kazi na data
xml_set_character_data_handler($xml_parser, "data");

// fungua faili
$fp = fopen($file, "r");

$perviy_vxod = 1; // bendera ili kuangalia ingizo la kwanza kwenye faili
$data = "" ; // hapa tunakusanya data kutoka kwa faili katika sehemu na kuituma kwa kichanganuzi cha xml

// kitanzi hadi mwisho wa faili upatikane
wakati (! feof ($fp) na $fp)
{
$ simvol = fgetc ($ fp); // soma herufi moja kutoka kwa faili
$data .= $simvol ; // ongeza herufi hii kwa data itakayotumwa

// ikiwa mhusika sio lebo ya mwisho, basi rudi mwanzo wa kitanzi na ongeza herufi nyingine kwenye data, na kadhalika hadi lebo ya mwisho ipatikane.
if($simvol != ">" ) (endelea;)
// ikiwa lebo ya kufunga ilipatikana, sasa tutatuma data hii iliyokusanywa kwa usindikaji

// angalia ikiwa hii ndiyo kiingilio cha kwanza kwenye faili, basi tutafuta kila kitu kilicho kabla ya lebo// kwa kuwa wakati mwingine unaweza kukutana na takataka kabla ya kuanza kwa XML (wahariri wasio na akili, au faili ilipokelewa na hati kutoka kwa seva nyingine)
if($perviy_vxod ) ( $data = strstr ($data , "

// sasa tupa data kwenye kichanganuzi cha xml
ikiwa (! xml_parse ($xml_parser, $data, feof ($fp))) (

// hapa unaweza kuchakata na kupokea makosa ya uhalali...
// mara tu hitilafu inapotokea, uchanganuzi huacha
mwangwi"
Hitilafu ya XML: " . xml_error_string(xml_get_error_code($xml_parser));
echo "kwenye mstari". xml_get_current_line_nambari ($xml_parser);
mapumziko;
}

// baada ya kuchanganua, tupa data iliyokusanywa kwa hatua inayofuata ya mzunguko.
$data = "" ;
}
fclose($fp);
xml_parser_free($xml_parser);
// kuondoa vigezo vya kimataifa
unset($GLOBALS [ "webi_depth" ]);
unset($GLOBALS [ "webi_tag_open" ]);
unset($GLOBALS [ "webi_data_temp" ]);

Webi_xml("1.xml");

?>

Mfano mzima unaambatana na maoni, sasa jaribu na majaribio.
Tafadhali kumbuka kuwa katika kazi ya kufanya kazi na data, data haijaingizwa tu kwenye safu, lakini inaongezwa kwa kutumia " .=" kwa kuwa data haiwezi kufika kwa ukamilifu, na ikiwa utafanya tu kazi, basi mara kwa mara utapokea data kwa vipande.

Naam, hiyo ndiyo yote, sasa kuna kumbukumbu ya kutosha wakati wa kusindika faili ya ukubwa wowote, lakini muda wa uendeshaji wa script unaweza kuongezeka kwa njia kadhaa.
Ingiza chaguo la kukokotoa mwanzoni mwa hati
set_time_limit(6000);
au
ini_set ("max_execution_time" , "6000" );

Au ongeza maandishi kwenye faili ya .htaccess
php_value max_execution_time 6000

Mifano hii itaongeza muda wa uendeshaji wa hati hadi sekunde 6000.
Unaweza kuongeza muda kwa njia hii tu wakati hali salama imezimwa.

Ikiwa una ufikiaji wa kuhariri php.ini unaweza kuongeza wakati wa kutumia
max_execution_time = 6000

Kwa mfano, kwenye mwenyeji wa Masterhost, wakati wa kuandika makala hii, kuongeza muda wa hati ni marufuku, licha ya hali salama kuzimwa, lakini ikiwa wewe ni mtaalamu, unaweza kutengeneza PHP yako mwenyewe kwenye Masterhost, lakini hiyo ni. si katika makala hii.

Siku nyingine nilianza kurekebisha mfumo wangu wa kuripoti wa ndani kwa kampuni, muundo wa jumla ambao niliandika juu yake sio muda mrefu uliopita. Bila prevarication, nitasema kwamba nimekua juu yangu mwenyewe kwa suala la PHP, na, kwa sababu hiyo, niligundua kuwa algorithm ya mfumo imepotoshwa vya kutosha ili niweze kuiandika tena.

Kabla ya hili, hati ya XML ilichanganuliwa kwa kutumia vitendaji ambavyo vilikopwa kutoka kwa toleo la 4 la PHP. Walakini, PHP5 iliipa ulimwengu kitu rahisi sana kinachoitwa SimpleXML. Leo tutazungumza juu ya jinsi ya kufanya kazi nayo.

Inafaa kuanza na ukweli kwamba SimpleXML ni moduli tofauti ya programu-jalizi, na kwa hivyo lazima iwezeshwe mapema kwenye seva unayotumia.

Sasa tunaweza kufanya kazi!

Ili kuchakata hati, tunatumia kazi ya simplexml_load_file(). Kama kigezo, hupitishwa anwani ya faili katika Lugha ya Alama Iliyoongezwa (XML - Umbizo lako la K.O.).

Uzuri wa kazi hii ni kwamba unaweza kuhamisha faili kwa urahisi kutoka kwa seva yoyote. Kwa hivyo, tuna fursa ya kuchakata upakiaji wa nje wa xml (kwa mfano, Yandex-XML au milisho ya RSS ya watu wengine).

Chaguo za kukokotoa hutoa safu. Shimo nililokumbana nalo ni kwamba XML inaweza kuwa na muundo tata, na kwa hivyo nakushauri kwanza utekeleze ufuatiliaji wa kitamathali na utoe safu ili kuelewa jinsi kazi iliichakata. Baada ya hayo, unaweza kuanza usindikaji wa data iliyopokelewa.

Kwa mfano, nitachukua muundo rahisi kutoka hapa:


>
>
> PHP: Kuibuka kwa Parser >
>
>
> Bi. Koda >
> Onlivia Acta >
>
>
> Bwana. Koda >
> Muigizaji wa El >
>
> > Bwana. Mchanganuzi > > John Doe > > >
>
Kwa hivyo ni lugha. Bado ni lugha ya programu. Au
hii ni lugha ya maandishi? Yote yamefunuliwa katika filamu hii,
kama filamu ya kutisha.
>
>
> PHP hutatua shida zangu zote za wavuti >
>
7>
5>
PG > >
>

Acha hii iwe faili ya export.xml, ambayo iko kwenye mzizi wa seva yangu pamoja na hati inayoichakata.
Safu imejengwa kwa mujibu wa muundo wa vipengele vya DOM katika hati ya XML. Usindikaji huanza kutoka kwenye mizizi. Ili kupata jina la Bi. Coder, ni lazima tutengeneze njia ifuatayo: $xml->movies->movie->wahusika->wahusika->jina.
Tafadhali kumbuka kuwa tunachagua thamani maalum. Hapa ndipo aina hii ya nukuu ya mhusika inatoka - usisahau kuwa tunafanya kazi na safu!

Kama safu yoyote, data yetu inaweza kuchakatwa kwa kutumia kitanzi cha mbele. Kanuni itakuwa kama hii:

$xml = simplexml_load_file ("export.xml" ) ; // faili iliyopakiwa
$ttl = $xml -> movies -> movie -> title ; // nimepata kichwa. kuna moja tu, kwa hivyo hakuna haja ya kuweka thamani nyingine

foreach ($xml -> sinema -> sinema -> wahusika kama $crc) // sasa tufanye kazi katika mienendo
{
//onyesha majina ya mashujaa
$name = $crc -> tabia -> jina ;
mwangwi (" $jina
"
) ;
}

Nambari hii itaweka maandishi "PHP: Parser Inaonekana" katika kigezo cha $ttl, na kisha kuonyesha majina ya mashujaa mstari kwa mstari kwenye skrini.
Bi. Mwanasimba, Bw. Mwanasimba, Bw. Mchanganuzi.

Kichanganuzi cha Xml ni programu ambayo hutoa data kutoka kwa faili chanzo cha xml na kuihifadhi au kuitumia kwa vitendo vifuatavyo.

Kwa nini vichanganuzi vya xml vinahitajika?

Kwanza kabisa, kwa sababu muundo wa xml yenyewe ni maarufu kati ya viwango vya kompyuta. Faili ya XML inaonekana kama hii:

hizo. kimsingi kuna vitambulisho, kuna sheria ambazo vitambulisho vinapaswa kufuatana.

Sababu ya umaarufu wa faili za xml ni kwamba zinaweza kusomeka sana na wanadamu. Na ukweli kwamba ni rahisi kusindika katika programu.

Ubaya wa faili za xml.

Kikwazo ni, kwanza kabisa, kiasi kikubwa cha nafasi ya disk ambayo data hii inachukua. Kwa sababu ya ukweli kwamba vitambulisho vinavyorudiwa mara kwa mara, na idadi kubwa ya data, huchukua megabytes nyingi, ambazo zinahitaji tu kupakuliwa kutoka kwa chanzo, na kisha kusindika. Je, kuna njia mbadala? Kuna, bila shaka, lakini bado, vichanganuzi vya xml na xml leo ni mojawapo ya miundo rahisi na ya kuaminika na maarufu ya kiteknolojia.

Vichanganuzi vya XML vimeandikwaje?

Vichanganuzi vimeandikwa katika lugha za programu. Kama wanasema, zimeandikwa kwa kila mtu, lakini sio zaidi. Inapaswa kueleweka kuwa kuna lugha za programu ambazo tayari zina maktaba zilizojengwa kwa kuchanganua faili za xml. Lakini kwa hali yoyote, hata ikiwa hakuna maktaba, unaweza kupata maktaba inayofaa kwa suala hili kila wakati na kuitumia kutoa data kutoka kwa faili.

Ulimwenguni, kuna njia 2 tofauti za kuchanganua faili za xml.

Ya kwanza ni kupakia faili ya xml kabisa kwenye kumbukumbu na kisha kufanya ghiliba kutoa data.

Ya pili ni chaguo la utiririshaji. Katika kesi hii, lugha ya programu inafafanua vitambulisho fulani ambavyo kazi za kichanganuzi kilichoundwa cha xml zinahitaji kuguswa, na mpangaji programu mwenyewe anaamua kile kinachohitajika kufanywa ikiwa lebo fulani imegunduliwa.

Faida ya njia ya kwanza ni kasi. Mara moja nilipakua faili, kisha nikakimbia haraka kupitia kumbukumbu yangu na nikapata kile kilichohitajika na, muhimu zaidi, rahisi kupanga. lakini kuna minus na muhimu sana - hii

kiasi kikubwa cha kumbukumbu kinahitajika kwa uendeshaji. Wakati mwingine, ningesema mara nyingi hutokea kwamba haiwezekani kusindika na kuchambua faili ya xml, i.e. unda kichanganuzi cha xml ili njia ya kwanza ifanye kazi kwa usahihi. Kwanini hivyo? Kweli, kwa mfano, kizuizi cha programu 32-bit chini ya Windows inaruhusu programu kuchukua kumbukumbu ya gigabytes 2 - hii haiwezekani tena.

Walakini, upangaji wa msingi wa nyuzi ni ngumu. Ugumu wa uchimbaji mbaya huongezeka kwa kiasi kikubwa, ambayo inathiri vyema muda na bajeti.

Uhalali wa faili za xml na vichanganuzi.

Kila kitu kitakuwa sawa na faili za xml na vichanganuzi vya xml, lakini kuna shida. Kwa sababu ya ukweli kwamba "mtoto yeyote wa shule" anaweza kuunda faili ya xml, na kwa kweli hii ni kweli (kwa sababu nambari nyingi huandikwa na watoto wa shule), faili zisizo sahihi zinaonekana, yaani sio sahihi. Hii inamaanisha nini na imejaa nini. Shida kubwa zaidi, hii ni kwamba wakati mwingine haiwezekani kuchanganua faili batili kwa usahihi. Kwa mfano, vitambulisho vyake havifungwi kama mtu angetarajia kulingana na kiwango, au kwa mfano, usimbaji umewekwa vibaya. Tatizo jingine ni kwamba ikiwa, kwa mfano, unatengeneza kichanganuzi kwenye .net, basi unaweza kuunda kinachojulikana kama wrappers , na jambo la kuudhi zaidi ni kwamba unatengeneza kanga kama hiyo, na kisha kuitumia kusoma faili ambayo "mwanafunzi" aliunda. , lakini faili ni batili na haiwezi kusomeka. Kwa hivyo, lazima uiondoe na uamue chaguzi zisizopendwa sana za kuchanganua faili kama hizo. Na zote kutoka =kutokana na ukweli kwamba wengi huunda faili za xml bila kutumia maktaba za kawaida. na kwa chuki kamili kwa viwango vyote vya faili za xml. Hili ni gumu kuelezea kwa wateja. Wanasubiri matokeo - kichanganuzi cha xml ambacho hubadilisha data kutoka kwa faili asili hadi umbizo lingine.

Jinsi ya kuunda vichanganuzi vya xml (chaguo la kwanza)

Kuna lugha ya maswali ya data ya XML inayoitwa Xpath. Lugha hii ina matoleo mawili; hatutaingia kwa undani kuhusu vipengele vya kila toleo. Wazo bora la lugha hii litaonyeshwa na mifano ya jinsi ya kuitumia kutoa data. Kwa mfano.

//div[@class="supcat guru"]/a

ombi hili linafanya nini. Inachukua lebo zote ambazo nina rejeleo iliyo na maandishi catalog.xml?hid= na lebo hii inapaswa kuwa mtoto wa div ambaye darasa lake ni sawa na supcat guru.

Ndio, inaweza isiwe wazi vya kutosha mara ya kwanza, lakini bado unaweza kuigundua ikiwa unataka. Mahali pa kuanzia kwangu ni http://ru.wikipedia.org/wiki/XPath na nakushauri.

Majira ya joto yamefika na wiki ya kwanza ya Julai imepita. Katika wiki mbili lazima nitetee nadharia yangu, na moja ya sehemu zake ni Kichanganuzi cha XML. Lakini ni huruma kwamba haiko kwenye PHP. Vema, usijali, tutafika baada ya dakika moja

Nimeona vichanganuzi vingi vya xml, lakini sijagusa upangaji wa wavuti. Sasa nataka kujua na kujifunza na wewe jinsi ya kufanya rahisi kichanganuzi cha xml katika php.

Kwa ajili ya nini? Lazima!

Hapana, kwa kweli: faili za xml ni jambo muhimu sana. Na mtaalamu yeyote anapaswa ... hapana, haipaswi, lakini lazima ajue jinsi ya kufanya kazi nao. Tunataka kuwa wataalamu, sawa? Ikiwa uko kwenye blogi yangu, basi una hamu kama hiyo.

Tunadhania kuwa tunajua XML ni nini na hatutaielezea hapa. Kweli, ikiwa hatujui, tunaweza kujua kwa urahisi hapa: http://ru.wikipedia.org/wiki/XML

Wakati nikitafuta njia za kuchambua XML katika PHP, niligundua seti rahisi ya kazi katika PHP ya kufanya kazi na faili za XML zinazoitwa " Kazi za Kichanganuzi cha XML" Uchanganuzi huanza kwa kuanzisha kichanganuzi kwa kupiga kazi ya xml_parser_create:

$xml_parser = xml_parser_create();

Kisha tunahitaji kumwambia kichanganuzi ni kazi zipi zitachakata lebo za xml na maelezo ya maandishi ambayo hukutana nayo wakati wa uchanganuzi. Wale. unahitaji kusanikisha vidhibiti kadhaa:

xml_set_element_handler($xml_parser, “startElement”, “endElement”);

Chaguo hili la kukokotoa linawajibika kwa kuweka mwanzo wa kipengele na mwisho wa vidhibiti vya kipengele. Kwa mfano, ikiwa mchanganyiko unapatikana katika maandishi ya faili ya xml, kazi ya startElement itafanya kazi wakati mchanganuzi atapata kipengele, na kazi ya endElement itafanya kazi inapoipata.

Kazi za startElement na endElement zenyewe huchukua vigezo kadhaa kulingana na nyaraka za php:



// (kwani tunaweza kutumia vichanganuzi kadhaa)

// $attrs - safu ya sifa za kipengele kilichogunduliwa
) kazi endElement($parser, $name) (
// $parser - kitambulisho cha kipekee cha kichanganuzi
// $name - jina la kipengele kilichotambuliwa
}
?>

Lakini jinsi ya kusoma data kutoka kwa faili? Bado hatujaona parameta moja ya hii katika utendaji wowote! Na zaidi juu ya hili baadaye: kusoma faili hutegemea mabega ya programu, i.e. lazima tutumie utendaji wa kawaida kufanya kazi na faili:

Ilifungua faili. Sasa unahitaji kuisoma mstari kwa mstari na kulisha mistari iliyosomwa kwa xml_parse kazi:

Hapa tunaona mambo mawili muhimu sana. Ya kwanza ni kwamba kazi ya xml_parse inahitaji kupitishwa bendera ya usomaji wa mstari wa mwisho katika paramu ya tatu (kweli - ikiwa mstari ni wa mwisho, uwongo - ikiwa sivyo). Jambo la pili ni kwamba, kama katika biashara yoyote, lazima tuangalie makosa hapa. xml_get_error_code na xml_error_string vitendaji vinawajibika kwa hili. Kazi ya kwanza inapokea msimbo wa hitilafu, na ya pili, kulingana na msimbo uliopokea, inarudi maelezo ya maandishi ya kosa. Nini kitatokea kama matokeo ya makosa itajadiliwa baadaye. Chaguo za kukokotoa muhimu sawa na xml_get_current_line_number zitatuambia idadi ya laini ya sasa inayochakatwa kwenye faili.

Na kama kawaida, lazima tuachilie rasilimali zinazochukuliwa na mfumo. Kwa uchanganuzi wa XML, hii ndio kazi ya xml_parser_free:

xml_parser_free($xml_parser);

Hapa tumeangalia kazi kuu. Ni wakati wa kuwaona katika vitendo. Kwa hili nilikuja na faili ya xml na muundo rahisi sana:




123

71234567890

Hebu tuite faili hii data.xml na tujaribu kuichanganua kwa kutumia msimbo ufuatao:

kazi startElement($parser, $name, $attrs) (
global $depth;echo str_repeat(" ", $depth * 3); // indentation
mwangwi" Kipengele: $name
";// jina la kipengele

$kina++; // ongeza kina ili kivinjari kionyeshe indentation

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

ikiwa (!($fp = fopen($file, "r"))) (
die ("haikuweza kufungua pembejeo ya XML");
}

wakati ($data = fgets ($fp)) (
ikiwa (!xml_parse ($xml_parser, $data, feof ($fp))) (
mwangwi"
Hitilafu ya XML: ";
echo xml_error_string(xml_get_error_code($xml_parser));
echo " kwenye mstari ".xml_get_current_line_number($xml_parser);
mapumziko;
}
}

xml_parser_free($xml_parser);
?>

Kama matokeo ya hati rahisi zaidi tuliyotengeneza, kivinjari kilionyesha habari ifuatayo kwenye dirisha lake:

Element: ROOT Element: INFO Sifa: WHO = My Element: ADDRESS Sifa: ULICA = my street!! Sifa: KVARTIRA = 12 Sifa: DOM = 15 Kipengele: SIMU

Wacha tujaribu kupotosha faili ya XML kwa kubadilisha lebo Washa , na kuacha lebo ya kufunga sawa:

Element: ROOT Element: INFO Sifa: WHO = My Element: ADDRESS Sifa: ULICA = my street!! Sifa: KVARTIRA = 12 Sifa: DOM = 15 Elementi: SIMU

Hitilafu ya XML: Lebo isiyolingana kwenye mstari wa 5

Lo! Ujumbe wa makosa hufanya kazi! Na taarifa kabisa.

Eh, nilisahau jambo moja zaidi... Hatukuonyesha maandishi yaliyomo ndani ya anwani na vitambulisho vya simu. Tunasahihisha upungufu wetu - ongeza kidhibiti maandishi kwa kutumia kazi ya xml_set_character_data_handler:

xml_set_character_data_handler($xml_parser, 'stringElement');

Na ongeza kitendaji yenyewe kwa nambari:

Sasa hebu tuangalie matokeo:

Element: ROOT Element: INFO Sifa: WHO = My Element: ADDRESS Sifa: ULICA = my street!! Sifa: KVARTIRA = Sifa 12: DOM = Mfuatano 15: Kipengele cha 123: Mfuatano wa SIMU: +71234567890

KUHUSU! Sasa kila kitu kimetolewa!

Kwa njia, kuna mtu yeyote ameona kuwa lebo na majina ya sifa yameandikwa kwa herufi kubwa? Ajabu... zimeonyeshwa kwa herufi ndogo kwenye faili yetu ya xml. Inavyoonekana mipangilio mingine imewekwa mahali fulani kufanya herufi kubwa...

Ah, nimeipata! Inabadilika kuwa pia kuna chaguo la kukokotoa xml_parser_set_option:

xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);

Kwa simu hii tunaghairi uchapishaji wa majina ya sifa na majina ya lebo kwa herufi kubwa:

Kipengele: Kipengele cha mizizi: maelezo Sifa: nani = Kipengele changu: anwani Sifa: ulica = mtaa wangu!! Sifa: kvartira = 12 Sifa: dom = 15 Kamba: 123 Kipengele: Kamba ya simu: +71234567890

Katika makala hii, tuliangalia rahisi zaidi, lakini kwa kazi nyingi, njia ya kutosha ya kutoa habari kutoka kwa faili za XML. Pia nimesikia kuhusu njia zingine zenye nguvu zaidi, lakini nitazizingatia ninapojifunza kidogo mimi mwenyewe

nika, Unahitaji kuingiza simu
xml_set_character_data_handler($xml_parser, 'stringElement');
baada ya
xml_set_element_handler($xml_parser, “startElement”, “endElement”);

Kwa ujumla, kwa onyesho sahihi unahitaji kuzingatia yafuatayo:
1. faili ya xml lazima iwe katika usimbaji wa UTF-8
2. kwenye faili ya xml mstari wa kwanza unapaswa kuwa kama hii:
< ?xml version="1.0" encoding="UTF-8"?>
3. unahitaji kuanzisha kichanganuzi kama hiki:
xml_parser_create("UTF-8?);
4. Kabla ya kutoa yaliyomo kwenye faili ya xml kwa kivinjari, unahitaji kusanidi ya mwisho kwa usimbaji wa UTF-8:
kichwa(“Aina ya Maudhui: maandishi/html; charset=utf-8?);

Ili kuonyesha maandishi kwa Kirusi tunatumia
iconv("UTF-8?,"windows-1251?, $attr), ambapo $attr ndio inahitaji kutolewa.

Kuna madarasa mawili ya kupendeza katika maktaba ya kawaida ya PHP5 - DOMDocument() na XSLTProcesor() nilitumia kwenye miradi mikubwa kabisa - silalamiki =)

Kwa ujumla, PHP ina maktaba nyingine ya kuchanganua XML kwa kutumia kanuni ya SAX - inayoitwa XMLReader.

    Mabwana, ninawezaje kutoa vitambulisho visivyo vya kawaida kutoka kwa xml kwa kutumia simplexml, kwa mfano?
    Tofauti kama $text = $item->yandex:full-text haifanyi kazi.

    Kila kitu ni sawa, makini tu na uwepo wa parameter ifuatayo,

    kazi cdata($parser, $cdata)
    {
    var_dump($parser, $cdata);
    }

    xml_set_character_data_handler($this->kichanganuzi, "cdata");

    Bila hivyo, hataki kuchanganua XML na CDATA…. Ukubwa wa mita 1.5

    2Nika, Kichwa () kazi hufanya kazi tu ikiwa hakuna kitu kilichotolewa kabla yake, ambayo ni, ilifanywa kwanza, kwa sababu tunatuma vichwa kwenye ukurasa huu ambavyo hutuambia kuwa maandishi yanahitaji kubadilishwa kuwa usimbaji wa UTF-8. Kulingana na kosa lako, unayo mistari inayokosekana, kwa hivyo ifanye kama hii:

    Thamani == nambari ya mlolongo wa safu
    kichwa("Aina ya Maudhui: maandishi/html; charset=utf-8?); == 2

    Kila kitu ni rahisi zaidi katika ukweli
    yurban.ru/development/php_xml_parser