Portál AbcLinuxu, 9. května 2024 06:12


Dotaz: PHP xml parser a problém s českými znaky

otula avatar 1.8.2009 16:09 otula | skóre: 45 | blog: otakar | Adamov
PHP xml parser a problém s českými znaky
Přečteno: 1487×
Odpovědět | Admin
Potřeboval jsem na jedny skromnější stránky udělat jednoduchou fotogalerii. Programovat v PHP moc neumím, zvládám nějaké základy, s nimiž si obvykle tak nějak vystačím. A pro účel té fotogalerie jsem si upravil fotogalerii od Tomáše Párala. Vše funguje dobře až na problém, který je už v původním kódu. Pro popisky fotek se používá soubor popisky.txt - tam je vše v pořádku, ovšem název a popis galerie, autor a pár dalších informací se bere ze souboru config.xml, a tam nastává problém. Pokud je v některém popisu znak s diakritikou, parser před ním zastaví a tento ani další znaky již nezpracuje. A skočí na další položku. Psal jsem Tomášovi, ale odepsal mi, že se již dlouho PHP nevěnuje, ale že by ten problém měl být někde v parseru.

config.xml vypadá takto:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE conf SYSTEM "../config.dtd">
<conf>
	<const name="ROW_THUMB_NUM" desc="pocet nahledu na radce">3</const>
	<const name="PREFIX" desc="prefix souboru s nahledem">tn_</const>
	<const name="DESC_FILE" desc="nazev souboru s popiskami">popisky.txt</const>
	<const name="SHOW_DESC" desc="zobrazovat popisky u fotek [0|1]">1</const>
	<const name="SHOW_THUMB_DESC" desc="zobrazovat popisky i u nahledu [0|1]">1</const>
	<const name="IMPLICIT_DESC" desc="implicitni title a alt, tak kde neni popisek">obrázek</const>
	<const name="GALLERY_NAME" desc="popis galerie">Jarní květinky</const>
	<const name="DATE" desc="datum vytvoreni fotek"></const>
	<const name="AUTHOR" desc="autor fotografii">Oťula</const>
	<const name="NOTE" desc="poznamka k fotogalerii">Jsou opravdu překrásné</const>
</conf>
A parser vypadá takto (je v něm už doplněno i vše možné, co jsem poznacházel po webu ohledně UTF-8, že by mělo pomoci, ale nepomohlo):
function start_element($parser,$tag,$attr)
{
  global $at, $desc, $current;

  $current=$tag;
  if (strcmp($tag,"const")==0)
  {
    $at=$attr["name"];
  }
}

function end_element($parser,$tag)
{
  global $current;

  $current="";
}

function element_data($parser,$data)
{
  global $at,$current;

  if (strcmp($current,"const")==0)
  {
    define($at,$data);
  }
} 

function config($loc)
{
  if (!file_exists($loc))
  {
    return 0;
  }
  else
  {
    if(!($f=fopen($loc,"r")))
    {
      return 0;
    }
    else
    {
      $at="";
      $current="";
      $parser=xml_parser_create("UTF-8");
      xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING,"UTF-8");
      xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
      xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
      xml_set_element_handler($parser,"start_element","end_element");
      xml_set_character_data_handler($parser,"element_data");

      if(!xml_parse($parser,fread($f,filesize($loc))))
      {
        xml_parser_free($parser);
        return 0;
      }
    }
  xml_parser_free($parser);
  return 1;
  }
}
Při uvedených příkladech to tedy vypadá tak, že se název galerie zobrazí "Jarn", autor "O", implicitní title a alt "obr", a poznámka "Jsou opravdu p".

Byl bych vděčný za radu, jak to dát dohromady.
Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.

Řešení dotazu:


Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

1.8.2009 16:33 Andrej Herceg | skóre: 43
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Odpovědět | | Sbalit | Link | Blokovat | Admin
Keď to dám do php súboru, pridám k tomu správnu html hlavičku (kvôli kódovaniu) a takéto funkcie:
config("config.xml");
$dc = get_defined_constants(true);
echo "<pre>", print_r($dc["user"], true), "</pre>";
tak sa mi zobrazí niečo takéto:
Array
(
    [ROW_THUMB_NUM] => 3
    [PREFIX] => tn_
    [DESC_FILE] => popisky.txt
    [SHOW_DESC] => 1
    [SHOW_THUMB_DESC] => 1
    [IMPLICIT_DESC] => obrázek
    [GALLERY_NAME] => Jarní květinky
    [AUTHOR] => Oťula
    [NOTE] => Jsou opravdu překrásné
)
(a teda, mne to funguje normálne)
otula avatar 1.8.2009 16:44 otula | skóre: 45 | blog: otakar | Adamov
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Tak to jsem z toho jelen. No v souboru, který zobrazuje výsledek, je něco takového:
...

  //nacteni konstant z xml souboru
  include("./xml.php"); //nacteni xml parseru
  @$chyba = config($folder.$setting); //pokud nebyl config.xml nalezen, tak nastav hodnoty explicitne
    
  //implicitni nastaveni promenych z config.xml
  (!defined("THUMB_NUM"))?define("THUMB_NUM","15"):""; //9 nahledu na stranku
  (!defined("ROW_THUMB_NUM"))?define("ROW_THUMB_NUM","3"):""; // 3 nahledy na radku
  (!defined("PREFIX"))?define("PREFIX","tn_"):""; //prefix souboru s nahledy
  (!defined("DESC_FILE"))?define("DESC_FILE","popisky.txt"):""; //nazev souboru s popiskami
  (!defined("SHOW_DESC"))?define("SHOW_DESC","1"):""; // zobrazovat popisky u fotek
  (!defined("SHOW_THUMB_DESC"))?define("SHOW_THUMB_DESC","1"):""; // zobrazovat popisky u nahledu
  (!defined("IMPLICIT_DESC"))?define("IMPLICIT_DESC","obrázek"):""; // implicitni popiska 
  (!defined("GALERY_NAME"))?define("GALLERY_NAME",""):""; // nazev galerie
  (!defined("DATE"))?define("DATE",""):""; // datum vytvoreni fotek
  (!defined("AUTHOR"))?define("AUTHOR",""):""; // autor fotek
  (!defined("NOTE"))?define("NOTE",""):""; //poznamka k fotogalerii

...
...
...
...

//vypis nadpisu, autora a data porizeni fotek
  echo "<div id=\"hlavicka\">\n";
    echo (GALLERY_NAME != "" && defined("GALLERY_NAME"))?"<h2>".GALLERY_NAME."</h2>\n":"\n";
    echo (NOTE != "" && defined("NOTE"))?"<p>".NOTE."</p>\n":"\n";
    echo (AUTHOR != "" && defined("AUTHOR"))?"<p><strong>Autor: </strong>".AUTHOR."</p>\n":"\n";
    echo (DATE != "" && defined("DATE"))?"<p><strong>Datum: </strong>".DATE."</p>\n":"\n";
  echo "</div>\n"; 

...
...
...
a je to načítáno do souboru s takovouto hlavičkou:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
...

Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.
1.8.2009 16:47 Andrej Herceg | skóre: 43
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Určite je aj ten config.xml v kódovaní utf-8?
otula avatar 1.8.2009 16:53 otula | skóre: 45 | blog: otakar | Adamov
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Ano, určitě je. A zkoušel jsem ho schválně uložit i v kódování jiném, a to potom nenačetlo vůbec nic.
Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.
1.8.2009 17:19 Andrej Herceg | skóre: 43
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Funguje takéto niečo ?:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<?php
include("./xml.php");
@$chyba = config("config.xml");
$dc = get_defined_constants(true);
echo "<pre>", print_r($dc["user"], true), "</pre>";
?>
</body>
</html>
otula avatar 1.8.2009 17:29 otula | skóre: 45 | blog: otakar | Adamov
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Tohle se chová úplně stejně špatně - a už jsem napsal níže - zjistil jsem, že se problém projevuje pouze s PHP 5. Napadá tě, co by tam mělo být jinak kvůli pětkové verzi?
Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.
otula avatar 1.8.2009 16:57 otula | skóre: 45 | blog: otakar | Adamov
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Možná by bylo ještě dobré říct, že pokud například to slůvko "obrázek" smažu v config.xml a ponechám ho v tom souboru, odkud se načte, pokud v config.xml nic není, tak je to v pořádku.
Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.
otula avatar 1.8.2009 17:25 otula | skóre: 45 | blog: otakar | Adamov
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Andreji, přišel jsem asi na to, proč to tobě funguje, a mně ne. Zkusil jsem to nahrát ještě na jiný server, kde je starší PHP (verze 4.4) - tam to jede v pohodě. Nefunguje mi to na serverech s PHP 5.

Snad by to mohlo pomoct k nalezení řešení.
Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.
1.8.2009 17:56 Andrej Herceg | skóre: 43
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Skús mierne upraviť xml.php, tak, aby vypisoval, čo sa práve spracováva a budeš vidieť, v čom je problém. Môžeš vyskúšať niečo takéto (a ten skript, čo som posielal vyššie, aby sa ten xml súbor načítal):
<?php
function start_element($parser,$tag,$attr)
{
  global $at, $desc, $current;
echo "start_element: (", $tag, ", ", print_r($attr, true), ")<br>";
  $current=$tag;
  if (strcmp($tag,"const")==0)
  {
    $at=$attr["name"];
  }
}

function end_element($parser,$tag)
{
  global $current;
echo "end_element: (", $tag, ")<br>";
  $current="";
}

function element_data($parser,$data)
{
  global $at,$current;
echo "element_data: (", $data, ")<br>";
  if (strcmp($current,"const")==0)
  {
    define($at,$data);
  }
}

function config($loc)
{
  if (!file_exists($loc))
  {
    return 0;
  }
  else
  {
    if(!($f=fopen($loc,"r")))
    {
      return 0;
    }
    else
    {
      $at="";
      $current="";
      $parser=xml_parser_create("UTF-8");
      xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING,"UTF-8");
      xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
      xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
      xml_set_element_handler($parser,"start_element","end_element");
      xml_set_character_data_handler($parser,"element_data");

      if(!xml_parse($parser,fread($f,filesize($loc))))
      {
        xml_parser_free($parser);
        return 0;
      }
    }
  xml_parser_free($parser);
  return 1;
  }
}
?>
Zo zobrazovaných informácií je jasné, že sa bude musieť presunúť definovanie tej konštanty až do funkcie end_element (a v element_data sa bude ten text spájať).
otula avatar 1.8.2009 19:18 otula | skóre: 45 | blog: otakar | Adamov
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Díky. Výstup tohoto opravdu už něco vypovídá:
start_element: (const, Array ( [name] => GALLERY_NAME [desc] => nazev akce, odkud fotky pochazi ) )
element_data: (Jarn)
element_data: (í květinky)
end_element: (const)
element_data: ( )
start_element: (const, Array ( [name] => DATE [desc] => datum vytvoreni fotek ) )
end_element: (const)
element_data: ( )
start_element: (const, Array ( [name] => AUTHOR [desc] => autor fotografii ) )
element_data: (O)
element_data: (ťula)
end_element: (const)
element_data: ( )
start_element: (const, Array ( [name] => NOTE [desc] => poznamka k fotogalerii ) )
element_data: (Jsou opravdu p)
element_data: (řekrásné)
end_element: (const)
element_data: ( )
end_element: (conf)
Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.
Řešení 2× (otula (tazatel), David Opletal)
1.8.2009 18:06 Andrej Herceg | skóre: 43
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
Môžeš vyskúšať zmeniť xml.php na niečo takéto:
<?php
function start_element($parser,$tag,$attr)
{
  global $at, $element_data, $desc, $current;
  
  $current=$tag;
  if (strcmp($tag,"const")==0)
  {
    $at=$attr["name"];
    $element_data = "";
  }
}

function end_element($parser,$tag)
{
  global $at,$element_data,$current;

  if (strcmp($current,"const")==0)
  {
    define($at,$element_data);
  }
  $current="";
}

function element_data($parser,$data)
{
  global $at,$element_data,$current;

  if (strcmp($current,"const")==0)
  {
    $element_data .= $data;
  }
}

function config($loc)
{
  if (!file_exists($loc))
  {
    return 0;
  }
  else
  {
    if(!($f=fopen($loc,"r")))
    {
      return 0;
    }
    else
    {
      $at="";
      $current="";
      $parser=xml_parser_create("UTF-8");
      xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING,"UTF-8");
      xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
      xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
      xml_set_element_handler($parser,"start_element","end_element");
      xml_set_character_data_handler($parser,"element_data");

      if(!xml_parse($parser,fread($f,filesize($loc))))
      {
        xml_parser_free($parser);
        return 0;
      }
    }
  xml_parser_free($parser);
  return 1;
  }
}
?>
otula avatar 1.8.2009 19:21 otula | skóre: 45 | blog: otakar | Adamov
Rozbalit Rozbalit vše Re: PHP xml parser a problém s českými znaky
SUPER! Tohle funguje!

Andreji, jsi zlato! Kdybys byl holka, poslal bych ti pusu :-) Až budeš v Brně, máš u mne panáka :-)
Kdo vám tvrdí, že jste paranoidní, ten v tom spiknutí s největší pravděpodobností jede taky.

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.