Èñïîëüçîâàíèå XML â PHP

Äîñòàâêà öâåòîâ â Èçáåðáàø Ñëóæáà äîñòàâêè ñðåäè öâåòîâ.

Ýòà ñòàòüÿ, êàê Âû óæå ñêîðåå âñåãî ïîíÿëè èç íàçâàíèÿ, ïîñâÿùåíà òîìó, êàê ìîæíî èñïîëüçîâàòü XML äëÿ õðàíåíèÿ äàííûõ, êîòîðûå áóäóò èñïîëüçîâàòüñÿ èç ñêðèïòîâ, íàïèñàííûõ íà PHP. Áåäåì ñ÷èòàòü, ÷òî Âû óæå çíàåòå, ÷òî òàêîå XML è ñ ÷åì åãî åäÿò. Ïðèìåðû ê ñòàòüå Âû ìîæåòå ñêà÷àòü îòñþäà. Íàø ïëàí òàêîé. Ñíà÷àëà ìû óçíàåì, êàêèå ôóíêöèè åñòü äëÿ ðàáîòû ñ XML â PHP è êàê èìè ïîëüçîâàòüñÿ. ×òîáû ýòî ëó÷øå ïîíÿòü, ìû ðàññìîòðèì íåáîëüøîé ñêðèïò, êîòîðûé áóäåò îòîáðàæàòü ñòðóêòóðó íàøåãî XML-äîêóìåíòà.

Ïðèñòóïèì. Íå õî÷ó ÿ íóäíî è äîëãî ðàññêàçûâàòü îáùèå ñëîâà ïðî òî, êàê ðàáîòàòü ñ XML â PHP, ëó÷øå äàâàéòå ðàçáåðåì ýòî âñå íà ïðèìåðå. Èòàê, ïîñòàíîâêà çàäà÷è: íàïèñàòü ñêðèïò, êîòîðûé áóäåò ïîêàçûâàòü ñòðóêòóðó XML-äîêóìåíòà.  ïðèìåðàõ ýòî ôàéë xml.php.
Ñíà÷àëà ñîçäàäèì XML-äîêóìåíò (â ïðèìåðàõ ýòî test.xml). Ïóñòü â ýòîì ôàéëå áóäóò îïèñûâàòüñÿ ôîòîãðàôèè. Îñîáî ìóäðèòü ìû íå áóäåì, è îáîéäåìñÿ áåç îïèñàíèÿ DTD (íå ïóòàòü ñ DDT :)). Çäåñü ïîÿâëÿåòñÿ ïåðâàÿ íåïðèÿòíàÿ îñîáåííîñòü PHP: XML-äîêóìåíòû, êîòîðûå äîëæíû îáðàáàòûâàòüñÿ èç ñêðèïòà ìîãóò áóòü íàïèñàíû â ñëåäóþùèõ êîäèðîâêàõ: US-ASCII, ISO-8859-1 è UTF-8. Ò.ê. íàì íóæíî îïèñûâàòü ôîòîãðàôèè ïî-ðóññêè, òî ïðèäåòñÿ âûáðàòü ïîñëåäíþþ êîäèðîâêó, ò.ê. â ïåðâûõ äðóõ íåò ðóññêèõ áóêâ. Íå âñå òåêñòîâûå ðåäàêòîðû ìîãóò ðàáîòàòü ñ ýòîé êîäèðîâêîé. ß, íàïðèìåð, íàáèðàë XML â ðåäàêòîðå SciTE. Îí ìàëåíüêèé, áåñïëàòíûé è ó íåãî õîðîøàÿ ïîäñâåòêà ñèíòàêñèñà (â òîì ÷èñëå PHP è XML). Íàø XML-äîêóìåíò áóäåò âûãëÿäåòü òàê:
<?xml version="1.0" encoding="UTF-8"?>
<album>
<foto smallfoto="Fotos/1smallvelo.jpg " bigfoto="Fotos/1bigvelo.jpg ">
<title>Íàçâàíèå 1</title>
<comment>Äëèííûé êîììåíòàðèé
íà íåñêîëüêî ñòðîê 1</comment>
<date>26.05.2003</date>
<color/>
<detailed>0</detailed>
</foto>
<foto smallfoto="Fotos/smallbardak.jpg " bigfoto="Fotos/bigbardak.jpg ">
<title>Íàçâàíèå 2</title>
<comment> Äëèííûé êîììåíòàðèé
íà íåñêîëüêî ñòðîê 2</comment>
<date>27.05.2003</date>
<color/>
<detailed>1</detailed>
</foto>
</album>
"Ôèçè÷åñêèé" ñìûñë òåãîâ â XML ñåé÷àñ çíà÷åíèÿ íå èìååò (õîòÿ òàì âðîäå è òàê âñå ïîíÿòíî). Åäèíñòâåííîå, ÷òî òîëüêî <color/> çäåñü ìîæåò îáîçíà÷àòü öâåòíàÿ ôîòêà èëè íåò. Ýòî çäåñü òîëüêî äëÿ ïðèìåðà òåãà, ó êîòîðîãî íåò çàêðûâàþùåãîñÿ.
À òåïåðü íàïèøåì ñêðèïò, êîòîðûé ïîêàçûâàë áû ñòðóêòóðó XML-äîêóìåíòà. Äëÿ ðàáîòû ñ XML â PHP åñòü áîëüøå 20 ôóíêöèé. Ðàññìîòðèì äëÿ íà÷àëà ñàìûå íåîáõîäèìûå. Âîò ýòîò ñêðèïò:
<?
$xmlfilename = "test.xml";
$code = "UTF-8"; // Êîäèðîâêà xml-à
$curcode = "Windows-1251"; // Òåêóùàÿ êîäèðîâêà

$level = 0; // Óðîâåíü âëîæåííîñòè
$list = array(); // Ñïèñîê ýëåìåíòîâ â xml-ôàéëå

// Ïðåîáðàçóåò ñòðîêó èç Unicode
function encoding ($str)
{
global $code;
global $curcode;

$str = mb_convert_encoding($str, $curcode, $code);
return $str;
}

function drawspace()
{
global $level;
for ($i = 0; $i < $level * 10; $i++)
{
echo " ";
}
}

// Îáðàáàòûâàåò òåêñò ìåæäó òåãàìè
function characterhandler ($parser, $data)
{
global $code;
global $curcode;

drawspace();
$data = encoding($data, $curcode, $code);
$data = trim($data)."<br>";
echo $data;
}

// Îáðàáàòûâàåò îòêðûâàþùèåñÿ òåãè
function starthandler ($parser, $name, $attribs)
{
global $level;
global $list;

global $code;
global $curcode;

$name = encoding($name, $curcode, $code);
$list[] = $name;
drawspace();
echo "<<font color='blue' size='+1'>$name</font>";
foreach ($attribs as $atname => $val)
{
echo encoding("$atname => $val");
}
echo "><br>";
$level++;
}

// Îáðàáàòûâàåò çàêðûâàþùèåñÿ òåãè
function endhandler ($parser, $name)
{
global $level;
global $list;
array_pop($list);
$level--;
drawspace();
echo "<<font color='blue' size='+1'>/$name</font>><p>";
}

// Ñîçäàäèì ïàðñåð
$parser = xml_parser_create($code);
if (!$parser)
{
exit ("Íå ìîãó ñîçäàòü ïàðñåð");
}
else
{
echo "Ïàðñåð óñïåøíî ñîçäàí<p>";
}

// Óñòàíîâèì îáðàáîò÷èêè òåãîâ è òåêñòà ìåæäó íèìè
xml_set_element_handler($parser, 'starthandler', 'endhandler');
xml_set_character_data_handler($parser, 'characterhandler');

// Îòêðîåì ôàéë ñ xml
$fp = fopen ($xmlfilename, "r");
if (!$fp)
{
xml_parser_free($parser);
exit("Íå ìîãó îòêðûòü ôàéë");
}

while ($data = fread($fp, 4096))
{
if (!xml_parse($parser, $data, feof($fp)))
{
die(sprintf("Îøèáî÷êà âûøëà: %s â ñòðîêå %d",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
}
}

fclose ($fp);
xml_parser_free($parser);
?>
Ïîñëå îáúÿâëåíèé âñïîìîãàòåëüíûõ ôóíêöèé, íåîáõîäèìî â ïåðâóþ î÷åðåäü ñîçäàòü ïàðñåð. Ýòî ìîæíî ñäåëàòü îäíîé èç ôóíêöèèé xml_parser_create èëè xml_parser_create_ns. Ïåðâàÿ èìååò îäèí íåîáÿçàòåëüíûé ïàðàìåòð, êîòîðûé îáîçíà÷àåò êîäèðîâêó, â êîòîðîé íàïèñàí XML-äîêóìåíò. Åñëè åãî íå óêàçàòü, òî ïî-óìîë÷àíèþ ñ÷èòàåòñÿ, ÷òî îí íàïèñàí êàê ISO-8859-1. Íî, êàê ÿ ïèñàë âûøå, ýòî íàì íå ïîäõîäèò è ìû âûáèðàåò UTF-8. Ò.ê. îáîçíà÷åíèå ýòîé êîäèðîâêè íàì åùå ïîíàäîáèòñÿ, òî âûíåñåì åå â ãëîáàëüíóþ ïåðåìåííóþ ($code = "UTF-8";). Òàêæå âûíåñåì òóäà êîäèðîâêó, â êîòîðîé áóäåò âûâîäèòüñÿ òåêñò â áðàóçåð ($curcode = "Windows-1251";). Ôóíêöèÿ xml_parser_create_ns èìååò äîïîëíèòåëüíûé (òîæå íåîáÿçàòåëüíûé) ïàðàìåòð, êîòîðûé îáîçíà÷àåò ñèìâîë, êîòîðûì â äîêóìåíòå áóäóò ðàçäåëÿòüñÿ ïðîñòðàíñòâà èìåí. Ò.ê. íàì ñåé÷àñ ýòî íå íàäî, òî ìû âîñïîëüçîâàëèñü ïåðâîé ôóíêöèåé. Åñëè ïàðñåð ñîçäàí óñïåøíî, òî ïàðåìåííàÿ $parser ïîëó÷èò çíà÷åíèå, îòëè÷íîå îò íóëÿ.
Ïîñëå ýòîãî íàäî óêàçàòü ïàðñåðó XML, êàêèå ôóíêöèè âûçûâàòü ïðè ïîÿâëåíèè â òåêñòå òåãîâ XML. Â íàøåì ïðèìåðå ýòî ñäåëàíî òàê:
// Óñòàíîâèì îáðàáîò÷èêè òåãîâ è òåêñòà ìåæäó íèìè
xml_set_element_handler($parser, 'starthandler', 'endhandler');
xml_set_character_data_handler($parser, 'characterhandler');
Ôóíêöèÿ xml_set_element_handler óñòàíàâëèâàåò îáðàáîò÷èêè äëÿ îòêðûâàþùèõñÿ è çàêðûâàþùèõñÿ òåãîâ.  êà÷åñòâå ïåðâîãî ïàðàìåòðà èì ïåðåäàåòñÿ ïàðñåð, êîòîðûé ìû ñîçäàëè äî ýòîãî. À â êà÷åñòâå âòîðîãî è òðåòüåãî - èìåíà ôóíêöèé, êîòîðûå áóäóò âûçûâàòüñÿ ïî ìåðå òîãî, êàê áóäóò ïîïàäàòüñÿ îòêðûâàþùèåñÿ è çàêðûâàþùèåñÿ òåãî ñîîòâåòñòâåííî. Ýòè ôóíêöèè äîëæíû áûòü îïðåäåëåíû îïðåäåëåííûì îáðàçîì. Ôóíêöèÿ äëÿ îòêðûâàþùèõñÿ òåãîâ äîëæíà âûãëÿäåòü ïðèìåðíî òàê:
// Îáðàáàòûâàåò îòêðûâàþùèåñÿ òåãè
function starthandler ($parser, $name, $attribs)
{
}
Ïðè åå âûçîâå åé ïåðåäàþòñÿ ïàðñåð, êîòîðûé ìû ñîçäàëè, èìÿ îáðàáàòûâàåìîãî òåãà è åãî àòðèáóòû (òî, ÷òî íàõîäèòñÿ â óãëîâûõ ñêîáêàõ ïîñëå èìåíè). Åñëè ñ èìåíåì íèêàêèõ îñîáåííîñòåé íåò, òî àòðèáóòû ïåðåäàþòñÿ êàê àññîöèàòèâíûé ìàññèâ, ò.å. â âèäå êëþ÷ => çíà÷åíèå. Ïîýòîìó ìû èõ è îáðàáàòûâàåì ñëåäóþùèì îáðàçîì:

foreach ($attribs as $atname => $val)
{
echo encoding("$atname => $val");
}
Âñå òîæå ñàìîå è äëÿ çàêðûâàþùèõñÿ òåãîâ, òîëüêî ôóíêöèè íå ïåðåäàþòñÿ àòðèáóòû, êîòîðûõ â ïðèíöèïå áûòü íå ìîæåò ó çàêðûâàþùåãîñÿ òåãà:
function endhandler ($parser, $name)
{
}
Òóò åñòü îäíà èíòåðåñíàÿ äåòàëü. Äàæå åñëè ó òåãà íåò çàêðûâàþùåãîñÿ, òî âòîðàÿ ôóíêöèÿ âñå-ðàâíî âûçûâàåòñÿ. Åñëè Âû ïîñìîòðèòå íà ðàáîòó ñêðèïòà, òî óâèäèòå, ÷òî äëÿ òåãà <color/> ó íàñ ïîëó÷èëîñü:
<COLOR>
</COLOR>
À ÷òîáû îáðàáàòûâàòü òåêñò, êîòîðûé ðàñïîëàãàåòñÿ ìåæäó òåãàìè, íàäî óñòàíîâèòü ñîîòâåòñòâóþùèé îáðàáîò÷èê ôóíêöèåé xml_set_character_data_handler. Åé ïîëüçîâàòüñÿ òî÷íî òàê æå, òîëüêî åå âòîðûì àðãóìåíòîì äîëæíî áûòü èìÿ ôóíêöèè, êîòîðàÿ îáúÿâëåíà òàêèì îáðàçîì:
function characterhandler ($parser, $data)
Òî åñòü òàê æå, êàê è äëÿ çàêðûâàþùåãîñÿ òåãà. Èìåííî â íåå ïåðåäàþòñÿ âñå äàííûå íàïîäîáèå "Íàçâàíèå 1" èëè "Äëèííûé êîììåíòàðèé íà íåñêîëüêî ñòðîê 2" èç íàøåãî ïðèìåðà. Íó è, íàêîíåö, ñàìîå ãëàâíîå - êàê ÷èòàòü XML-äîêóìåíò. Îêàçûâàåòñÿ ïðîñòî - êàê îáû÷íûé òåêñòîâûé ôàéë. Ò.å. îòêðûâàåì åãî ôóíêöèåé fopen, íàïðèìåð òàê:
$fp = fopen ($xmlfilename, "r");
È ÷èòàåì èç íåãî âñå ñòðîêè, êîòîðûå ïîòîì ïåðåäàåì â ôóíêöèþ xml_parse:
while ($data = fread($fp, 4096))
{
if (!xml_parse($parser, $data, feof($fp)))
{
die(sprintf("Îøèáî÷êà âûøëà: %s â ñòðîêå %d",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
}
}
Ó xml_parse òðè àðãóìåíòà. Ïåðâûé - ïåðåìåííàÿ ñîçäàííîãî íàìè ðàíüøå ïàðñåðà, âòîðîé - ïðî÷èòàííàÿ ñòðîêà, à òðåòèé (íåîáÿçàòåëüíûé) - ïðèçíàê òîãî, ÷òî ïîðà çàêàí÷èâàòü ïàðñèòü (âîò ìû òóäà è ïåðåäàåì çíà÷åíèå òîãî, êîí÷èëñÿ ëè ôàéë). Ó íàñ åùå âñòàâëåíà ïðîâåðêà îøèáîê. Òàì âðîäå âñå ÿñíî èç íàçâàíèÿ. xml_get_error_code âîçâðàùàåò êîä îøèáêè, ïî êîòîðîìó xml_error_string ñîçäàåò ñòðîêó, êîòîðàÿ îïèñûâàåò ýòó îøèáêó.
Ïîñëå âñåãî ýòîãî íàäî íå çàáûòü óíè÷òîæèòü ïàðñåð. Ýòî äåëàåòñÿ ôóíêöèåé xml_parser_free:
xml_parser_free($parser);
Òåïåðü îäíà èç ñàìûõ íåïðèÿòíûõ îñîáåííîñòåé. Ò.ê. ìû ïèñàëè XML êàê Unicode, òî è ñòðîêè íàì ïåðåäàþòñÿ â òîé æå êîäèðîâêå. À òàê êàê îáû÷íî ñàéò ñòðîÿò íà áîëåå ïðèâû÷íîé êîäèðîâêå (Koi8, Windows), òî ñ ýòèì Unicod'îì íàäî ÷òî-òî äåëàòü. È âîò çäåñü íà÷èíàåòñÿ ñàìîå íåïðèÿòíîå.  ðàñøèðåíèè PHP, êîòîðîå îòâå÷àåò çà XML, åñòü äâå ôóíêöèè äëÿ ïåðåêîäèðîâêè UTF-8. Ýòî ôóíêöèÿ utf8_decode, êîòîðàÿ ïðåîáðàçóåò ñòðîêó èç UTF-8, è ôóíêöèÿ utf8_encode, êîòîðàÿ íàîáîðîò ïðåîáðàçóåò â UTF-8. Íî îíè íàì íå ïîäõîäÿò ïî òîé ïðè÷èíå, ÷òî ìîãóò ðàáîòàòü ñ êîäèðîâêîé ISO-8859-1, â êîòîðîé íåò ðóññêèõ áóêâ. Ê ñ÷àñòüþ, ðàçðàáîò÷èêè PHP âñå-òàêè ñäåëàëè ôóíêöèè, êîòîðûå ìîãóò áóç ïðîáëåì ðàáîòàòü è ñ äðóãèìè êîäèðîâêàìè - ýòî mb_convert_encoding.  äàííîì ñëó÷àå ìû åå èñïîëüçîâàëè òàê:
$str = mb_convert_encoding($str, $curcode, $code);
$curcode è $code ýòî ïåðåìåííûå, â êîòîðûõ õðàíÿòüñÿ íàçâàíèÿ êîäèðîâîê (ïîìíèòå, ìû èõ ðàíüøå îáúÿâèëè ãëîáàëüíûìè?). Ñ ýòîé ôóíêöèåé âñå ïîíÿòíî: ïåðâûé àðãóìåíò - ýòî èñõîäíàÿ ñòðîêà, âòîðîé - íàçâàíèå êîäèðîâêè, â êîòîðóþ ïðåîáðàçóåì, à òðåòèé àðãóìåíò (íåîáÿçàòåëüíûé) - êîäèðîâêà, èç êîòîðîé ïðåîáðàçóåì. Ôóíêöèÿ âîçâðàùàåò íàì íîâóþ ñòðîêó. Êàçàëîñü áû, ÷òî âñå õîðîøî, åñòü ôóíêöèÿ, îíà çäîðîâî ðàáîòàåò (ýòî äåéñòâèòåëüíî òàê), íî, ÷òîáû îíà ðàáîòàëà, íàäî, ÷òîáû áûëî ïîäêëþ÷åíî ðàñøèðåíèå ê PHP - mbstring (multi byte string). Äëÿ ýòîãî, åñëè âû ðàáîòàåòå èç Windows, â ôàéëå php.ini íàäî ðàñêîììåíòèðîâàòü ñòðîêó extension=php_mbstring.dll. Íî åñëè äîìà ýòî ñäåëàòü íåñëîæíî, òî âîò íà õîñòèíãå, ãäå ðàñïîëîæåí Âàø ñàéò, îíî (ðàñøèðåíèå) ìîæåò áûòü íå ïîäêëþ÷åíî. Èìåííî ïîýòîìó ÿ âûíåñ ïåðåêîäèðîâêó â îòäåëüíóþ ôóíêöèþ, ÷òîáû åå ìîæíî áûëî ëåãêî èñïðàâèòü:
// Ïðåîáðàçóåò ñòðîêó èç Unicode
function encoding ($str)
{
global $code;
global $curcode;

$str = mb_convert_encoding($str, $curcode, $code);
return $str;
}
Åñëè ó Âàñ åñòü èäåè íàñ÷åò òîãî, êàê îáîéòèñü áåç mb_convert_encoding - ïèøèòå ìíå
Ýòî áûëè ñàìûå ïðîñòûå ôóíêöèè äëÿ ðàáîòû ñ XML. ×òîáû áûëî èíòåðåñíåå, â íàøåì ñêðèïòå ÿ ñ÷èòàþ óðîâåíü âëîæåííîñòè äëÿ òåãîâ (ýòî äëÿ òîãî, ÷òîáû ïðàâèëüíî ñìåùàòü òåêñò âïðàâî) è åùå â ãëîáàëüíóþ ïåðåìåííóþ $list çàíîñÿòñÿ îòêðûâàþùèåñÿ òåãè, à ïðè ïîÿâëåíèè çàêðûâàþùåãîñÿ - âûáðàñûâàåòñÿ ïîñëåäíèé ýëåìåíò. Ò.î. â $list õðàíèòñÿ ïóòü ïî êîòîðîìó ìû ïðîøëè äî òåêóùåãî òåãà, à ñàì ýòîò òåã íàõîäèòñÿ â êîíöå ñïèñêà.
Òåïåðü äàâàéòå íåìíîãî ïîáàëóåìñÿ è ïîñìîòðèì, êàê ðàáîòàåò îáðàáîòêà îøèáîê. Óáåðåì èç òåãà color ñëåø. Òî åñòü îñòàâèì <color>, êàê áóäòî ìû çàáûëè åãî çàêðûòü. È âîò ÷òî íàì âûäàåò PHP: "Îøèáî÷êà âûøëà: mismatched tag â ñòðîêå 16". È íà ýòîì îáðàáîòêà ïðåêðàùàåòñÿ. Òàêæå "mismatched tag" áóäåò, åñëè ìû ïåðåíåñåì çàêðûâàþùèéñÿ òåã <data/> ïîñëå òåãà <foto/>.
Ïîèãðàåìñÿ ñ êîäèðîâêàìè. Åñëè ñîõðàíèòü íàø XML-äîêóìåíò â êîäèðîâêå Windows-1251 è ÷åñòíî ýòî óêàçàòü â çàãîëîâêå <?xml version="1.0" encoding="Windows-1251"?> (íå çàáóäüòå èñïðàâèòü ñîîòâåòñòâóþùóþ ãëîáàëüíóþ ïåðåìåííóþ â ñêðèïòå), òî PHP... áëàãîïîëó÷íî âûëåòàåò :) Ïî êðàéíåé ìåðå, òàê áûëî ó ìåíÿ. ß ýòîò ñêðèïò èñïûòûâàë íà òàêîé êîíôèãóðàöèè: Win2000 + SP3; Apache 1.3.27; PHP 4.3.1.
Ïîêà âðîäå áû âñå. Åñëè áóäóò âîïðîñû è çàìå÷àíèÿ - ïèøèòå ìíå

Àâòîð íåèçâåñòåí



Ïðè ïåðåïå÷àòêå èíôîðìàöèè äåëàéòå, ïîæàëóéñòà, ññûëêó íà íàø ñàéò (ëèáî ïîäåëèòüñÿ âêîíòàêòå, ãóãë+ èëè äåëèòåñü â îäíîêëàññíèêàõ ñòàòü¸é). Ñïàñèáî!

Èñòî÷íèê: www.wr-script.ru©
, 2004-2026ã.

Äåëèòåñü ñ äðóçüÿìè â ñîöñåòÿõ. Àêòèâíûå êîììåíòàòîðû ïîëó÷àþò ñâåæèå ñêðèïòû è áåñïëàòíûå äîðàáîòêè îò WR-Script.ru!

Âåðíóòüñÿ ê ñòàòüÿì ïîìîùè WEB-ìàñòåðó

WR-Счётчик