Tvorba XML výstupu v PHP
Občas pravděpodobně potřebujete ve svých PHP skriptech generovat XML výstup. Můžete k tomu použít různé metody, od jednoduchého „lepení textu“, přes třídy pro generování XML, až po XML DOM funkce. V tomto článku vám ukáži, jak si můžete takovou jednoduchou třídu pro tvorbu XML vytvořit.
Struktura třídy
Nejdříve si určíme strukturu v níž budou data uložena, jaké metody a jak se budou používat.
Vlastní data
Všechny elementy XML budou uloženy v číselně indexovaném poli. Každý prvek pole je asociativním polem s těmito parametry:
parent
– určuje index nadřazeného prvkutype
– typ elementu může nabývat tyto hodnoty:node
– uzel (element) XML tvořený startovním a případně i koncovým tagem,entity
– XML entita ohraničená řetězci&
a;
,cdata
– textová nebo jiná data v XML (nejsou tím myšlena data v parametrech) anote
– poznámka ohraničená znaky<!--
a-->
data
– v případě, že se jedná o typcdata
, obsahuje tento prvek samotná datatext
– v případě, že se jedná o typnote
, obsahuje tento prvek text poznámkyname
– v případě, že se jedná o typnode
, obsahuje tento prvek jméno uzlu (tagů), pokud je typentity
, obsahuje název entityparams
– v případě, že se jedná o typnode
, může tento prvek obsahovat parametry počátečního tagu v asociativním poli, klíč prvku pole určuje název parametru a hodnota prvku hodnotu parametru
Tato data budou uložena ve vlastnosti třídy data
.
Další vlasnoti třídy
xml_version
– určuje verzi XML, která bude zapsána v hlavičcexml_encoding
– určuje kodování XML, které bude zapsáno v hlavičce. Třída neprovádí žádné překódování mezi znakovými sadami, tuto vlastnost nastavte na takovou hodnotu, aby odpovídala kódování, v němž budou ukládaná data.auto_indent
– určuje řetězec, kterým se odsazují jednotlivé úrovně XML, je přednastaven na dvě mezery. Můžete zadat například mezeru, tabulátor nebo i více mezer. Pokud zadáte prázdný řetězec, nebude se odsazení provádět.append_after_element
– určuje řetězec, který se přidá za konec tagu, je přednastaven na znak konce řádky\n
.
Jen pro úplnost ještě uvedu zdrojový kód hlavičky třídy:
class c_xml_generator {
var $data = array();
var $auto_indent = ‚ ‚;
var $append_after_element = „\n“;
var $xml_version = ‚1.0‘;
var $xml_encoding = ‚iso-8859-2‘;
Metody třídy
PHP v současné produkční verzi (4.x) nerozlišuje mezi public
a private
metodami, proto, aby bylo jasné, o který typ metody se jedná, budeme odlišovat public
metody podtržítkem na začátku názvu metody.
Zjištění volného indexu v poli data
function _get_new_id() {
if (count($this->data) > 0)
return(array_reduce(array_keys($this->data), ‚max‘) + 1);
else
return(1);
}
Tato metoda zjistí volný index v poli data
. To je index, na který se bude ukládat další XML element. Tato metoda je využívána všemi metodami, které vkládají do XML obsah.
Přidání elementu
Metoda nejprve najde volný index v poli data
, následně na toto místo uloží data elementu a nakonec vrátí id nově vytvořeného prvku. Obdobným způsobem fungují i následující metody:
function add_node($parent, $name, $params=array()) {
$new_id = $this->_get_new_id();
$this->data[$new_id] = array(
‚type‘ => ‚node‘,
‚parent‘ => $parent,
‚params‘ => $params,
‚name‘ => $name
);
return($new_id);
}
Parametr metody $parent
obsahuje id nadřazeného prvku. V případe, že vytváříme element v nejvyšší úrovni, má tento parametr hodnotu 0
. Dalším parametrem je $name
, už podle názvu jistě poznáte, že obsahuje jméno elementu. Posledním parametrem $params
, kterým předáváte parametry elementu (tento parametr není povinný).
Přidání textových dat
function add_cdata($parent, $data) {
$new_id = $this->_get_new_id();
$this->data[$new_id] = array(
‚type‘ => ‚cdata‘,
‚parent‘ => $parent,
‚data‘ => $data
);
return($new_id);
}
Parametr metody $parent
obsahuje id nadřazeného prvku. Nadřazený prvek musí být typu node
. Dalším parametrem je $data
, který obsahuje samotná data.
Přidání entity
function add_entity($parent, $name) {
$new_id = $this->_get_new_id();
$this->data[$new_id] = array(
‚type‘ => ‚entity‘,
‚parent‘ => $parent,
‚name‘ => $name
);
return($new_id);
}
Parametr $parent
obsahuje id nadřazeného uzlu a $name
název entity.
A nakonec poznámky
function add_note($parent, $text) {
$new_id = $this->_get_new_id();
$this->data[$new_id] = array(
‚type‘ => ‚note‘,
‚parent‘ => $parent,
‚text‘ => $text
);
return($new_id);
}
Parametr $parent
obsahuje id nadřazeného uzlu a $text
text poznámky bez úvodní a koncové značky (<!--
a -->
). U této metody si musíte dát pozor na to, aby text vkládané poznámky neobsahoval počáteční a koncové značky poznámky.
Všechny tyto metody vracejí po vložení části XML její id. To budete potřebovat hlavně pro vytváření uzlů a poduzlů.
Formát vstupních dat
Ještě než se pustíme tvorby samotného XML kódu, řekneme si něco o tom, jak připravit data pro předcházející metody. Třída automaticky konvertuje nebezpečné znaky při tvorbě výsledného XML kódu, takže pokud použijete pro tvorbu uzlu například kód $xml_generator->add_node($id, 'uzel', array('parametr'=>'<!"');
, ve výsledném kódu se objeví <uzel parametr="<!"">
. Toto se provádí hlavně pro zjednodušení práce a také proto, abyste se vyhnuli zbytečným chybám.
Metody pro tvorbu XML kódu
Nejprve začneme pomocnými metodami:
function _encode_param_name($text) {
return(htmlspecialchars($text));
}
function _encode_param_value($text) {
return(str_replace(
array(„\n“,“\r“),
array(‚&x0A;‘,’&x0D‘),
htmlspecialchars($text)
));
}
function _encode_cdata($text) {
return(htmlspecialchars($text));
}
Tyto tři metody provádějí konverzi nebezpečných znaků pro textová data a parametry. Rozdíl mezi převodem textu a hodnot parametrů je ten, že u parametrů se navíc převádí i konce řádků \n
a \r
na entity.
Vlastní tvorba XML
function create_xml($start_node=0) {
return($this->_create_xml_node($start_node));
}
Tato metoda vytvoří výsledné XML tím, že zavolá metodu _create_xml_node
, která rekurzivně vytvoří celý dokument. Metoda má jeden nepovinný parametr, který určuje počáteční uzel. Výchozí hodnota je 0
, to znamená celý dokument.
Nyní se podíváme na „jádro“ celé třídy, metodu _create_xml_node
:
function _create_xml_node($id) {
static $level = 0;
$level++; // zvýší statickou proměnnou $level o jednu
// tato promenná se používá pro počítání odsazení
$node = &$this->data[$id];
switch($node[‚type‘]) {
case ‚node‘ : // pokud se jedná o typ node vytvoří nejprve
// startovní tag s parametry
$ret = ‚<‚.$node[‚name‘];
foreach($node[‚params‘] as $param_name => $param_value) {
$ret .= ‚ ‚.$this->_encode_param_name($param_name).
‚=“‚.$this->_encode_param_value($param_value).'“‚;
};
$childs = “;
$complete_tag = true;
// najde vsechny objekty patřící do tohoto node
foreach($this->data as $node_id => $node_data)
if ($node_data[‚parent‘] == $id) {
$complete_tag = false;
$childs .= $this->_create_xml_node($node_id);
// pro každý objekt volá rekurzívne metodat
// sama sebe
};
// podle toho jestli existují vypise tag jako
// párový nebo nepárový
if ($complete_tag)
$ret .= ‚ />‘;
else
$ret .= ‚>‘.$this->append_after_element.
$childs.
str_repeat($this->auto_indent, $level – 1).
‚</‘.$node[‚name‘].‘>‘;
break;
// pokud se jedná o ostatní typy cdata,entity
// note vypíše tak jak mají vypadat.
case ‚cdata‘ :
$ret = $this->_encode_cdata($node[‚data‘]);
break;
case ‚entity‘ :
$ret = ‚&‘.$node[‚name‘].‘;‘;
break;
case ‚note‘ :
$ret = ‚<!–‚.$this->_encode_cdata($node[‚text‘]).‘–>‘;
break;
case ‚root‘ : // typ root se zpracovává podobně jako node
$ret = ‚<‚.‘?xml‘.
($this->xml_version?‘ version=“‚.$this->xml_version.'“‚:“).
($this->xml_encoding?‘ encoding=“‚.$this->xml_encoding.'“‚:“).
‚?‘.“>\n“;
foreach($this->data as $node_id => $node_data)
if ($node_data[‚parent‘] == 0) {
$complete_tag = false;
$ret .= $this->_create_xml_node($node_id);
};
break;
};
$level–; // jsme na konci objektu, zmensi hodnotu odsazení
$ret = str_repeat($this->auto_indent, $level).
$ret.
$this->append_after_element;
return($ret); // a vrátí zpracovanou část dokumentu
}
A nakonec ještě ukázka, jak například pomocí třídy vytvořit XML export tabulky MySQL databáze. Používám třídu tMysql, o které jsem psal v článku Zjednodušte si práci s MySQL.
<?php
// pomocí hlavičky určíme mime typ text/xml
header(‚content-type: text/xml‘);
// vložíme třídu pro mysql a xml
include ‚xml_generator.class.php‘;
include ‚xmysql.class.php‘;
// název tabulky
$tb_name = ‚test‘;
// vytvoříme instanci třídy tMysql a připojíme k db
$sql = new tMysql;
$sql->dbName = ‚test‘;
$sql->dbHost = ‚localhost‘;
$sql->dbUser = ‚uzivatel‘;
$sql->dbPassword = ‚heslo‘;
$sql->connect();
// vytvoříme instanci třídy c_xml_generator
$xml = new c_xml_generator;
// vytvoříme si nejvyšší element
$top = $xml->add_node(0, ‚table‘, array(‚name‘ => $tb_name));
// vybereme data z požadované tabulky
$sql->query(‚export‘, ‚SELECT * FROM ‚.$tb_name);
// pro kazdý prvek výsledku vytvoříme jeden element
// —
while($row = $sql->fetch_assoc(‚export‘)) {
$xml->add_node($top, ‚row‘, $row);
};
// —
$sql->free_result(‚export‘);
echo $xml->create_xml();
?>
Předchozí kód vytvoří export v následujícím formátu:
<?xml version=“1.0″ encoding=“iso-8859-2″?>
<table name=“test“>
<row id=“1285″ jmeno=“Pajda“ druh=“pes“ heslo=“123″ />
<row id=“4″ jmeno=“Pepa“ druh=“andulka“ heslo=““ />
<row id=“145″ jmeno=“Rum“ druh=“pes“ heslo=““ />
<row id=“745″ jmeno=“Micka“ druh=“kočka“ heslo=““ />
</table>
Nebo pokud část kódu mezi značkami // ---
změníte takto…
while($row = $sql->fetch_assoc(‚export‘)) {
// element pro řádek tabulky
$xrow = $xml->add_node($top, ‚row‘);
foreach($row as $field => $value) {
// element pro pole tabulky
$xfield = $xml->add_node($xrow, $field);
// samotná data
$xml->add_cdata($xfield, $value);
};
};
…výsledek bude takový:
<?xml version=“1.0″ encoding=“iso-8859-2″?>
<table name=“test“>
<row>
<id>1285</id>
<jmeno>Pajda</jmeno>
<druh>pes</druh>
<heslo>123</heslo>
</row>
<row>
<id>4</id>
<jmeno>Pepa</jmeno>
<druh>andulka</druh>
<heslo> </heslo>
</row>
<row>
<id>145</id>
<jmeno>Rum</jmeno>
<druh>pes</druh>
<heslo> </heslo>
</row>
<row>
<id>745</id>
<jmeno>Micka</jmeno>
<druh>kočka</druh>
<heslo> </heslo>
</row>
</table>
Teď už vám zbývá jen stáhnout si zdrojový kód třídy a ukázky a začít s vlastními pokusy.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Mohlo by vás také zajímat
-
Landing page: Jak vytvořit landing page s vysokým CTR
7. května 2024 -
Jak vybrat doménu: Co je dobré vědět?
2. září 2024
Nejnovější
-
Výkonný a kompaktní: ASOME Max Studio s výjimečným poměrem cena/výkon
11. listopadu 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
OpenAI představilo novou funkci ChatGPT Search
6. listopadu 2024
Jozef mostka
Led 22, 2010 v 12:49chýba mi tam destroy metóda.
ako zničím triedu ?
Wictorko
Kvě 22, 2011 v 22:18Existuje an nejaky sposob ako to spravit opacne? Teda XML export z cudzieho webu si data natiahnut do vlastnej MySQL databazy?