PHP kézikönyv
Előző |  | Következő

# CLXVIII. XML értelmező függvények

# Bevezetés

Az XML (eXtensible Markup Language) olyan adatformátum, amit a Weben keresztüli adatcserére terveztek. Ezt az ajánlást a World Wide Web Consortium (W3C) dolgozta ki és gondozza. További információk az XML-ről és a kapcsolódó technológiákról a http://www.w3.org/XML/ címen található.

Ez a kiterjesztés James Clark expat könyvtárát használja, amely a http://www.jclark.com/xml/expat.html címen beszerezhető. Ez lehető teszi XML dokumentumok beolvasását, ún. elemzését, de nemazok érvényesítését. Három különböző PHP által is támogatott forrás-karakterkódolást támogat: US-ASCII, ISO-8859-1 és UTF-8. UTF-16 nincs támogatva.

Ez a kiterjesztés lehetőséget nyújt arra, hogy XML elemzőket hozzunk létre és azokhoz saját kezelőfüggvényeket rendeljünk hozzá, amelyek más és más események esetén futnak le. Minden XML elemzőnek néhány paramétere beállítható, ami a működését befolyásolja.

# Követelmények

Ez a kiterjesztés az expat könyvtárat használja, amely a http://www.jclark.com/xml/expat.html címen beszerezhető. A Makefile, amely ezzel a csomaggal jön alapértelmezés szerint nem telepíti a nekünk szükséges eljáráskönyvtárat, ehhez a következő sorokat kell beleírni:

    libexpat.a: $(OBJS)
        ar -rc $@ $(OBJS)
        ranlib $@

Elérhető forrás RPM csomag is a következő helyen: http://sourceforge.net/projects/expat/, ha nem akarsz kínlódni a fordítással ;)

# Telepítés

Az Apache 1.3.7 vagy későbbi verziójával már együtt jár az expat könyvtár. Ekkor a PHP-t csak egyszerűen a --with-xml opcióval kell fordítani - minden kiegészítő elérési útvonal nélkül - és ekkor az Apacheüba épített expat könyvtárat használja majd.

Az UNIX rendszereken a configure parancsot kell a --with-xml kapcsolóval. Az expat könyvtárnak olyan helyen kell installálva lennie, ahol a fordító el tudja érni. Ha a PHP-t modulként Apache 1.3.9 (ennek vagy későbbi verziójú) alá installálod, akkor a PHP automatikusan az Apache beépített expat eljáráskönyvtárat fogja használni. Szükség lehet CPPFLAGS és a LDFLAGS környezeti változók beállítására a rendszeren, mielőtt elindítod a configure parancsot, ha az expat-ot valamilyen egzotikus helyre installálták.

A PHP telepítése.... Tada! Ezt kell(ene) látnod!

# Futásidejű beállítások

Ez a kiterjesztés semmilyen konfigurációs beállításokat nem definiál a `php.ini` állományban.

# Erőforrás típusok

Ez a kiterjesztés semmilyen erőforrás típust nem definiál.

# Előre definiált állandók

Az itt listázott állandókat ez a kiterjesztés definiálja, és csak akkor elérhetőek, ha az adott kiterjesztés be van fordítva a PHP-be, vagy dinamikusan betöltött.

`XML_ERROR_NONE` (integer)

`XML_ERROR_NO_MEMORY` (integer)

`XML_ERROR_SYNTAX` (integer)

`XML_ERROR_NO_ELEMENTS` (integer)

`XML_ERROR_INVALID_TOKEN` (integer)

`XML_ERROR_UNCLOSED_TOKEN` (integer)

`XML_ERROR_PARTIAL_CHAR` (integer)

`XML_ERROR_TAG_MISMATCH` (integer)

`XML_ERROR_DUPLICATE_ATTRIBUTE` (integer)

`XML_ERROR_JUNK_AFTER_DOC_ELEMENT` (integer)

`XML_ERROR_PARAM_ENTITY_REF` (integer)

`XML_ERROR_UNDEFINED_ENTITY` (integer)

`XML_ERROR_RECURSIVE_ENTITY_REF` (integer)

`XML_ERROR_ASYNC_ENTITY` (integer)

`XML_ERROR_BAD_CHAR_REF` (integer)

`XML_ERROR_BINARY_ENTITY_REF` (integer)

`XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF` (integer)

`XML_ERROR_MISPLACED_XML_PI` (integer)

`XML_ERROR_UNKNOWN_ENCODING` (integer)

`XML_ERROR_INCORRECT_ENCODING` (integer)

`XML_ERROR_UNCLOSED_CDATA_SECTION` (integer)

`XML_ERROR_EXTERNAL_ENTITY_HANDLING` (integer)

`XML_OPTION_CASE_FOLDING` (integer)

`XML_OPTION_TARGET_ENCODING` (integer)

`XML_OPTION_SKIP_TAGSTART` (integer)

`XML_OPTION_SKIP_WHITE` (integer)

# Eseménykezelők

A definiálható XML eseménykezelők:

Táblázat 1. A támogatott XML eseménykezelők:

PHP függvány ,amely regisztrálja a kezelőt | esemény leírása
--- | ---
xml_set_element_handler() | Elem esemény akkor történik, amikor az XML elemző egy elem kezdő vagy zárócímkéjével találkozik. A nyító és zárócímkékhez külön eseménykezelők rendelhetők.

xml_set_character_data_handler()

(Elemzett) szöveges adatnak tekinthető durván minden, ami az XML dokumentumban nem a jelölésekhez tartozó tartalom, beleértve a jelölések közti térközöket is. Az XML elemző nem ad és nem vesz el semmilyen térkökaraktert az elemzés során a dokumentumból, ez teljes mértékben a feldolgozó alkalmazás feladata, illetve annak eldöntése, hogy ezek a karakterek értékes információt jelentenek vagy sem.

xml_set_processing_instruction_handler() | PHP programozók számára ismerős lehet a feldolgozó utasítás (proccesing instructions: PI) fogalma. A <?php ?> maga is ilyen, ahol a php a feldolgozó utasítás "célpontja", magyarán a megcélzott feldolgozó. Ezek mind az alkalmazásfüggő elemek, kivéve az XML jelölésűeket, amely lefoglalt ebben az esetben is.
xml_set_default_handler() | Azok az adatok, amelyek semmilyen más kezelő nem kezel le, ehhez a függvényhez kerülnek, pl.: XML és dokumentumtípus deklaráció.
xml_set_unparsed_entity_decl_handler() | Ezt a kezelőt hívja meg az elemző, ha jelölés deklarációs egyedet (unparsed, NDATA entity). kell feldolgozni.
xml_set_notation_decl_handler() | Ez a kezelő felelős a jelölések deklarációjáért.
xml_set_external_entity_ref_handler() | Ezt az kezelőt hívja meg az elemző, ha egy külső egyedhivatkozást talál. Ez lehet állományra vagy URL-re történő hivatkozás. Lásd a Példák külső egyedek kezelésére c. fejezetet!

# Betű egységesítés (case-folding)

Az elemek nevei kisbetűket és nagybetűket vegyesen tartalmazhatnak. Az elemkezelő fügvények szempontjából ez nem mindegy, ezért az XML szabvány definiált egy betűkezelő szabályt, mely szerint "ha kisbetűt, nagybetűt vegyesen tartalmazó karaktersorozatot kell feldolgozni, akkor a karaktersorozatban a kisbetűket ki kell cserélni a nekik megfelelő nagybetűkre". Más szavakkal, amikor egy karaktersorozat érkezik az XML értelmezőhöz, a betűkezelés egyszerűen a teljes nagybetűre váltást jelenti.

Alapértelmezés szerint az XML kezelők már nagybetűre váltott formában kapják meg a neveket az értelmezőtől. Ez a viselkedés azonban lekérdezhető ill. megváltoztatható az XML elemző következő két függvényével: xml_parser_get_option() (lekérdezés) és a xml_parser_set_option() (beállítás) függvényekkel.

# Hibaüzenetek

A következő hibaüzeneteket definálták (az xml_parse() függvény visszatérési értékei lehetnek):

XML_ERROR_NONE
XML_ERROR_NO_MEMORY
XML_ERROR_SYNTAX
XML_ERROR_NO_ELEMENTS
XML_ERROR_INVALID_TOKEN
XML_ERROR_UNCLOSED_TOKEN
XML_ERROR_PARTIAL_CHAR
XML_ERROR_TAG_MISMATCH
XML_ERROR_DUPLICATE_ATTRIBUTE
XML_ERROR_JUNK_AFTER_DOC_ELEMENT
XML_ERROR_PARAM_ENTITY_REF
XML_ERROR_UNDEFINED_ENTITY
XML_ERROR_RECURSIVE_ENTITY_REF
XML_ERROR_ASYNC_ENTITY
XML_ERROR_BAD_CHAR_REF
XML_ERROR_BINARY_ENTITY_REF
XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
XML_ERROR_MISPLACED_XML_PI
XML_ERROR_UNKNOWN_ENCODING
XML_ERROR_INCORRECT_ENCODING
XML_ERROR_UNCLOSED_CDATA_SECTION
XML_ERROR_EXTERNAL_ENTITY_HANDLING

# Karakterkódolások

A PHP XML kiterjesztése támogatja az Unicode karakterkészeletet különböző karakterkódolások által. Kétféle karakterkódolás különböztetünk meg, az ún. forrás kódolást és a cél kódolást. A PHP belső, értelmezési célokra a dokumentumokat mindig UTF-8 karakterkódolás szerint kódolja.

A forrás-kódolás az XML dokumentum értelmezése, elemzése során használja. Az XML értelmezőt létrehozásakor meg lehet határozni az elemző forrás kódolását, amit később már nem lehet megváltoztatni. A támogatott karakterkészletek a forrás kódolás számára a következők: ISO-8859-1, US-ASCII és az UTF-8. Az első kettő egybájtos kódolás, ami annyit tesz, hogy minden karaktert egyetlen bájton ábrázolnak. Az UTF-8 egy és négy bájt között különböző hosszúságú bitláncon (21 hosszúig) tudja ábrázolja a karaktereket. A forrás kódolás alapértelmezett karakterkészlete a PHP-ben a ISO-8859-1.

A cél-kódolás akkor készül el, amikor a PHP átadja az adatokat az XML kezelő függvényeknek. Amikor egy XML elemző létrejön, a cél-kódolás a forrás-kódolásához igazodik, de ezt meg lehet változtatni a későbbiek során. A cél-kódolás hatással lesz a karakteres adatra, XML elemek címkéire és a feldolgozó utasításokban definiált célpontokra is!

Ha az XML elemző olyan karaktert talál, mely nincs definiálva a forrás-kódolás karakterkészletében, akkor ez hibát okoz.

Ha az értelmezett XML dokumentumban találkozik a PHP egy olyan karakterrel, amit nem nem tud megjeleníteni a cél-kódolás karakterkészlete, akkor a problémás karaktert "lefokozza". Ez annyit jelent, hogy kérdőjelet rak a helyébe.

# Példák

Here are some example PHP scripts parsing XML documents.

## XML Element Structure Example

This first example displays the stucture of the start elements in a document with indentation.

Példa 1. Show XML Element Structure

`<?php
$file = "data.xml";
$depth = array();
function startElement($parser, $name, $attrs) {
global $depth;
for ($i = 0; $i < $depth[$parser]; $i++) {
print " ";
}
print "$name\n";
$depth[$parser]++;
}
function endElement($parser, $name) {
global $depth;
$depth[$parser]--;
}
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);`

## XML Tag Mapping Example

Példa 2. Map XML to HTML

This example maps tags in an XML document directly to HTML tags. Elements not found in the "map array" are ignored. Of course, this example will only work with a specific XML document type.

`$file = "data.xml";
$map_array = array(
"BOLD" => "B",
"EMPHASIS" => "I",
"LITERAL" => "TT"
);
function startElement($parser, $name, $attrs) {
global $map_array;
if ($htmltag = $map_array[$name]) {
print "<$htmltag>";
}
}
function endElement($parser, $name) {
global $map_array;
if ($htmltag = $map_array[$name]) {
print "</$htmltag>";
}
}
function characterData($parser, $data) {
print $data;
}
$xml_parser = xml_parser_create();
// use case-folding so we are sure to find the tag in $map_array
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);`

## XML External Entity Example

This example highlights XML code. It illustrates how to use an external entity reference handler to include and parse other documents, as well as how PIs can be processed, and a way of determining "trust" for PIs containing code.

XML documents that can be used for this example are found below the example (`xmltest.xml` and `xmltest2.xml`.)

Példa 3. External Entity Example

`$file = "xmltest.xml";
function trustedFile($file) {
// only trust local files owned by ourselves
if (!eregi("^([a-z]+)://", $file)
&& fileowner($file) == getmyuid()) {
return true;
}
return false;
}
function startElement($parser, $name, $attribs) {
print "&lt;<font color=\"#0000cc\">$name</font>";
if (sizeof($attribs)) {
while (list($k, $v) = each($attribs)) {
print " <font color=\"#009900\">$k</font>=\"<font
color=\"#990000\">$v</font>\"";
}
}
print "&gt;";
}
function endElement($parser, $name) {
print "&lt;/<font color=\"#0000cc\">$name</font>&gt;";
}
function characterData($parser, $data) {
print "<b>$data</b>";
}
function PIHandler($parser, $target, $data) {
switch (strtolower($target)) {
case "php":
global $parser_file;
// If the parsed document is "trusted", we say it is safe
// to execute PHP code inside it. If not, display the code
// instead.
if (trustedFile($parser_file[$parser])) {
eval($data);
} else {
printf("Untrusted PHP code: <i>%s</i>",
htmlspecialchars($data));
}
break;
}
}
function defaultHandler($parser, $data) {
if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") {
printf('<font color="#aa00aa">%s</font>',
htmlspecialchars($data));
} else {
printf('<font size="-1">%s</font>',
htmlspecialchars($data));
}
}
function externalEntityRefHandler($parser, $openEntityNames, $base, $systemId,
$publicId) {
if ($systemId) {
if (!list($parser, $fp) = new_xml_parser($systemId)) {
printf("Could not open entity %s at %s\n", $openEntityNames,
$systemId);
return false;
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($parser, $data, feof($fp))) {
printf("XML error: %s at line %d while parsing entity %s\n",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser), $openEntityNames);
xml_parser_free($parser);
return false;
}
}
xml_parser_free($parser);
return true;
}
return false;
}
function new_xml_parser($file) {
global $parser_file;
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
xml_set_processing_instruction_handler($xml_parser, "PIHandler");
xml_set_default_handler($xml_parser, "defaultHandler");
xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler");
if (!($fp = @fopen($file, "r"))) {
return false;
}
if (!is_array($parser_file)) {
settype($parser_file, "array");
}
$parser_file[$xml_parser] = $file;
return array($xml_parser, $fp);
}
if (!(list($xml_parser, $fp) = new_xml_parser($file))) {
die("could not open XML input");
}
print "<pre>";
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d\n",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
print "</pre>";
print "parse complete\n";
xml_parser_free($xml_parser);
?>`

Példa 4. xmltest.xml

    <?xml version='1.0'?>
    <!DOCTYPE chapter SYSTEM "/just/a/test.dtd" [
    <!ENTITY plainEntity "FOO entity">
    <!ENTITY systemEntity SYSTEM "xmltest2.xml">
    ]>
    <chapter>
     <title>Title &plainEntity;</title>
     <para>
      <informaltable>
       <tgroup cols="3">
        <tbody>
         <row><entry>a1</entry><entry morerows="1">b1</entry><entry>c1</entry></row>
         <row><entry>a2</entry><entry>c2</entry></row>
         <row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
        </tbody>
       </tgroup>
      </informaltable>
     </para>
     &systemEntity;
     <section id="about">
      <title>About this Document</title>
      <para>
       <!-- this is a comment -->
       <?php print 'Hi!  This is PHP version '.phpversion(); ?>
      </para>
     </section>
    </chapter>

This file is included from `xmltest.xml`:

Példa 5. xmltest2.xml

    <?xml version="1.0"?>
    <!DOCTYPE foo [
    <!ENTITY testEnt "test entity">
    ]>
    <foo>
       <element attrib="value"/>
       &testEnt;
       <?php print "This is some more PHP code being executed."; ?>
    </foo>

Előző | Tartalom | Következő
xdiff_string_patch | Fel | utf8_decode