日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

php的xml分析函數(shù)

瀏覽:37日期:2024-02-14 08:48:26

首先我得承認(rèn)我喜歡計(jì)算機(jī)標(biāo)準(zhǔn)。如果每個人都遵從這個行業(yè)的標(biāo)準(zhǔn),互聯(lián)網(wǎng)將會是一個更好的媒體。使用標(biāo)準(zhǔn)化的數(shù)據(jù)交換格式才能使開放的和獨(dú)立于平臺的計(jì)算模式切實(shí)可行。這就是我作為XML愛好者的原因。

幸運(yùn)的是,我最喜愛的腳本語言不但支持XML而且對其支持正不斷加強(qiáng)。PHP可以讓我迅速將XML文檔發(fā)布到互聯(lián)網(wǎng)上,收集XML文檔的統(tǒng)計(jì)信息,將XML文檔轉(zhuǎn)換成其它格式。例如,我時常用PHP的XML處理能力來管理我用XML所寫的文章和書。

本文中,我將討論任何用PHP內(nèi)建的Expat解析器來處理XML文檔。通過范例,我將演示Expat的處理方法。同時,范例可以告訴你如何:

建立你自己的處理函數(shù); 將XML文檔轉(zhuǎn)換成你自己的PHP數(shù)據(jù)結(jié)構(gòu)

介紹Expat

XML的解析器,同樣稱為XML處理器,可以使程序訪問XML文檔的結(jié)構(gòu)和內(nèi)容。Expat是PHP腳本語言的XML解析器。它同時也運(yùn)用在其它項(xiàng)目中,例如Mozilla、Apache和Perl。

什么是基于事件的解析器?

XML解析器的兩種基本類型:

基于樹型的解析器:將XML文檔轉(zhuǎn)換成樹型結(jié)構(gòu)。這類解析器分析整篇文章,同時提供一個API來訪問所產(chǎn)生樹的每個元素。其通用的標(biāo)準(zhǔn)為DOM(文檔對象模式)。; 基于事件的解析器:將XML文檔視為一系列的事件。當(dāng)一個特殊事件發(fā)生時,解析器將調(diào)用開發(fā)者提供的函數(shù)來處理。; 基 于事件的解析器有一個XML文檔的數(shù)據(jù)集中視圖,也就是說它集中在XML文檔的數(shù)據(jù)部分,而不是其結(jié)構(gòu)。這些解析器從頭到尾處理文檔,并將類似于-元素的 開始、元素的結(jié)尾、特征數(shù)據(jù)的開始等等-事件通過回調(diào)(callback)函數(shù)報(bào)告給應(yīng)用程序。以下是一個'Hello-World'的XML文檔范例:

<greeting>Hello World; </greeting>

基于事件的解析器將報(bào)告為三個事件:

開始元素:greeting; CDATA項(xiàng)的開始,值為:Hello World; 結(jié)束元素:greeting; 不像基于樹型的解析器,基于事件的解析器不產(chǎn)生描述文檔的結(jié)構(gòu)。在CDATA項(xiàng)中,基于事件的解析器不會讓你得到父元素greeting的信息。 然而,它提供一個更底層的訪問,這就使得可以更好地利用資源和更快地訪問。通過這種方式,就沒有必要將整個文檔放入內(nèi)存;而事實(shí)上,整個文檔甚至可以大于實(shí)際內(nèi)存值。

Expat就是這樣的一種基于事件的解析器。當(dāng)然如果使用Expat,必要時它一樣可以在PHP中生成完全的原生樹結(jié)構(gòu)。

上面Hello-World的范例包括完整的XML格式。但它是無效的,因?yàn)榧葲]有DTD(文檔類型定義)與其聯(lián)系,也沒有內(nèi)嵌DTD。

對于Expat,這并沒有區(qū)別:Expat是一個不檢查有效性的解析器,因此忽略任何與文檔聯(lián)系的DTD。但應(yīng)注意的是文檔仍然需要完整的格式,否則Expat(和其他符合XML標(biāo)準(zhǔn)的解析器一樣)將會隨著出錯信息而停止。

作為不檢查有效性的解析器,Exapt的快速性和輕巧性使其十分適合互聯(lián)網(wǎng)程序。

編譯Expat

Expat可以編譯進(jìn)PHP3.0.6版本(或以上)中。從Apache1.3.9開始,Expat已經(jīng)作為Apache的一部分。在Unix系統(tǒng)中,通過-with-xml選項(xiàng)配置PHP,你可以將其編譯入PHP。

如果你將PHP編譯為Apache的模塊,而Expat將默認(rèn)作為Apache的一部分。在Windows中,你則必須要加載XML動態(tài)連接庫。

XML范例:XMLstats

了解Expat的函數(shù)的一個辦法就是通過范例。我們所要討論的范例是使用Expat來收集XML文檔的統(tǒng)計(jì)數(shù)據(jù)。

對于文檔中每個元素,以下信息都將被輸出:

該元素在文檔中使用的次數(shù); 該元素中字符數(shù)據(jù)的數(shù)量; 元素的父元素; 元素的子元素; 注意:為了演示,我們利用PHP來產(chǎn)生一個結(jié)構(gòu)來保存元素的父元素和子元素

準(zhǔn)備

用 于產(chǎn)生XML解析器實(shí)例的函數(shù)為xml_parser_create()。該實(shí)例將用于以后的所有函數(shù)。這個思路非常類似于PHP中MySQL函數(shù)的連接 標(biāo)記。在解析文檔前,基于事件的解析器通常要求你注冊回調(diào)函數(shù)-用于特定的事件發(fā)生時調(diào)用。Expat沒有例外事件,它定義了如下七個可能事件:

對象 XML解析函數(shù) 描述

元素 xml_set_element_handler() 元素的開始和結(jié)束

字符數(shù)據(jù) xml_set_character_data_handler() 字符數(shù)據(jù)的開始

外部實(shí)體 xml_set_external_entity_ref_handler() 外部實(shí)體出現(xiàn)

未解析外部實(shí)體 xml_set_unparsed_entity_decl_handler() 未解析的外部實(shí)體出現(xiàn)

處理指令 xml_set_processing_instruction_handler() 處理指令的出現(xiàn)

記法聲明 xml_set_notation_decl_handler() 記法聲明的出現(xiàn)

默認(rèn) xml_set_default_handler() 其它沒有指定處理函數(shù)的事件

所有的回調(diào)函數(shù)必須將解析器的實(shí)例作為其第一個參數(shù)(此外還有其它參數(shù))。

對于本文最后的范例腳本。你需要注意的是它既用到了元素處理函數(shù)又用到了字符數(shù)據(jù)處理函數(shù)。元素的回調(diào)處理函數(shù)通過xml_set_element_handler()來注冊。

這個函數(shù)需要三個參數(shù):

解析器的實(shí)例; 處理開始元素的回調(diào)函數(shù)的名稱; 處理結(jié)束元素的回調(diào)函數(shù)的名稱; 當(dāng)開始解析XML文檔時,回調(diào)函數(shù)必須存在。它們必須定義為與PHP手冊中所描述的原型一致。

例如,Expat將三個參數(shù)傳遞給開始元素的處理函數(shù)。在腳本范例中,其定義如下:

function start_element($parser, $name, $attrs);

第一個參數(shù)是解析器標(biāo)示,第二個參數(shù)是開始元素的名稱,第三參數(shù)為包含元素所有屬性和值的數(shù)組。

一旦你開始解析XML文檔,Expat在遇到開始元素是都將調(diào)用你的start_element()函數(shù)并將參數(shù)傳遞過去。

XML的Case Folding選項(xiàng)

用xml_parser_set_option ()函數(shù)將Case folding選項(xiàng)關(guān)閉。這個選項(xiàng)默認(rèn)是打開的,使得傳遞給處理函數(shù)的元素名自動轉(zhuǎn)換為大寫。但XML對大小寫是敏感的(所以大小寫對統(tǒng)計(jì)XML文檔是非 常重要的)。對于我們的范例,case folding選項(xiàng)必須關(guān)閉。

解析文檔

在完成所有的準(zhǔn)備工作后,現(xiàn)在腳本終于可以解析XML文檔:

Xml_parse_from_file(),一個自定義的函數(shù),打開參數(shù)中指定的文件,并以4kb的大小進(jìn)行解析; xml_parse()和xml_parse_from_file()一樣,當(dāng)發(fā)生錯誤時,即XML文檔的格式不完全時,將會返回false。; 你可以使用xml_get_error_code()函數(shù)來得到最后一個錯誤的數(shù)字代碼。將此數(shù)字代碼傳遞給xml_error_string()函數(shù)即可得到錯誤的文本信息。; 輸出XML當(dāng)前的行數(shù),使得調(diào)試更容易。; 在解析的過程中,調(diào)用回調(diào)函數(shù)。; 描述文檔結(jié)構(gòu)

當(dāng)解析文檔時,對于Expat需要強(qiáng)調(diào)問題的是:如何保持文檔結(jié)構(gòu)的基本描述?

如前所述,基于事件的解析器本身并不產(chǎn)生任何結(jié)構(gòu)信息。

不 過標(biāo)簽(tag)結(jié)構(gòu)是XML的重要特性。例如,元素序列<book><title>表示的意思不同于< figure><title>。也就是說,任何作者都會告訴你書名和圖名是沒有關(guān)系的,雖然它們都用到'title'這個術(shù)語。因此, 為了更有效地使用基于事件的解析器處理XML,你必須使用自己的棧(stacks)或列表(lists)來維護(hù)文檔的結(jié)構(gòu)信息。

為了產(chǎn)生文檔結(jié)構(gòu)的鏡像,腳本至少需要知道目前元素的父元素。用Exapt的API是無法實(shí)現(xiàn)的,它只報(bào)告目前元素的事件,而沒有任何前后關(guān)系的信息。因此,你需要建立自己的棧結(jié)構(gòu)。

腳本范例使用先進(jìn)后出(FILO)的棧結(jié)構(gòu)。通過一個數(shù)組,棧將保存全部的開始元素。對于開始元素處理函數(shù),目前的元素將被array_push()函數(shù)推到棧的頂部。相應(yīng)的,結(jié)束元素處理函數(shù)通過array_pop()將最頂?shù)脑匾谱摺?

對于序列<book><title></title></book>,棧的填充如下:

開始元素book:將'book'賦給棧的第一個元素($stack[0])。; 開始元素title:將'title'賦給棧的頂部($stack[1])。; 結(jié)束元素title:從棧中將最頂部的元素移去($stack[1])。; 結(jié)束元素title:從棧中將最頂部的元素移去($stack[0])。; PHP3.0通過一個$depth變量手動控制元素的嵌套來實(shí)現(xiàn)范例。這就使腳本看起來比較復(fù)雜。PHP4.0通過array_pop()和array_push()兩個函數(shù)來使腳本看起來更簡潔。

收集數(shù)據(jù)

為了收集每個元素的信息,腳本需要記住每個元素的事件。通過使用一個全局的數(shù)組變量$elements來保存文檔中所有不同的元素。數(shù)組的項(xiàng)目是元素類的實(shí)例,有4個屬性(類的變量)

$count -該元素在文檔中被發(fā)現(xiàn)的次數(shù); $chars -元素中字符事件的字節(jié)數(shù); $parents -父元素; $childs - 子元素; 正如你所看到的,將類實(shí)例保存在數(shù)組中是輕而易舉的。

注意:PHP的一個特性是你可以通過while(list() = each())loop遍歷整個類結(jié)構(gòu),如同你遍歷整個相應(yīng)的數(shù)組一樣。所有的類變量(當(dāng)你用PHP3.0時還有方法名)都以字符串的方式輸出。

當(dāng)發(fā)現(xiàn)一個元素時,我們需要增加其相應(yīng)的記數(shù)器來跟蹤它在文檔中出現(xiàn)多少次。在相應(yīng)的$elements項(xiàng)中的記數(shù)元素也要加一。

我們同樣要讓父元素知道目前的元素是它的子元素。因此,目前元素的名稱將會加入到父元素的$childs數(shù)組的項(xiàng)目中。最后,目前元素應(yīng)該記住誰是它的父元素。所以,父元素被加入到目前元素$parents數(shù)組的項(xiàng)目中。

顯示統(tǒng)計(jì)信息

剩下的代碼在$elements數(shù)組和其子數(shù)組中循環(huán)顯示其統(tǒng)計(jì)結(jié)果。這就是最簡單的嵌套循環(huán),盡管輸出正確的結(jié)果,但代碼既不簡潔又沒有任何特別的技巧,它僅僅是一個你可能每天用他來完成工作的循環(huán)。

腳本范例被設(shè)計(jì)為通過PHP的CGI方式的命令行來調(diào)用。因此,統(tǒng)計(jì)結(jié)果輸出的格式為文本格式。如果你要將腳本運(yùn)用到互聯(lián)網(wǎng)上,那么你需要修改輸出函數(shù)來產(chǎn)生HTML格式。

總結(jié)

Exapt是PHP的XML解析器。作為基于事件的解析器,它不產(chǎn)生文檔的結(jié)構(gòu)描述。但通過提供底層訪問,這就使得可以更好地利用資源和更快地訪問。

作為一個不檢查有效性的解析器,Expat忽略與XML文檔連接的DTD,但如果文檔的格式不完整,它將會隨著出錯信息而停止。

提供事件處理函數(shù)來處理文檔; 建立自己的事件結(jié)構(gòu)例如棧和樹來獲得XML結(jié)構(gòu)信息標(biāo)記的優(yōu)點(diǎn)。; 每天都有新的XML程序出現(xiàn),而PHP對XML的支持也不斷加強(qiáng)(例如,增加了支持基于DOM的XML解析器LibXML)。

有了PHP和Expat,你就可以為即將出現(xiàn)的有效、開放和獨(dú)立于平臺的標(biāo)準(zhǔn)作準(zhǔn)備。

范例

<?; /*****************************************************************************; * 名稱:XML解析范例:XML文檔信息統(tǒng)計(jì) * 描述; * 本范例通過PHP的Expat解析器收集和統(tǒng)計(jì)XML文檔的信息(例如:每個元素出現(xiàn)的次數(shù)、父元素和子元素; * XML文件作為一個參數(shù) ./xmlstats_PHP4.php3 test.xml; * $Requires: Expat 要求:Expat PHP4.0編譯為CGI模式; *****************************************************************************/;

// 第一個參數(shù)是XML文件 $file = $argv[1]

// 變量的初始化 $elements = $stack = array()$total_elements = $total_chars = 0

// 元素的基本類 class element; {; var $count = 0var $chars = 0var $parents = array()var $childs = array()};

// 解析XML文件的函數(shù) function xml_parse_from_file($parser, $file); {; if(!file_exists($file)); {; die('Can't find file '$file'.')};

if(!($fp = @fopen($file, 'r'))); {; die('Can't open file '$file'.')};

while($data = fread($fp, 4096)); {; if(!xml_parse($parser, $data, feof($fp))); {; return(false)}; };

fclose($fp)

return(true)};

// 輸出結(jié)果函數(shù)(方框形式) function print_box($title, $value); {; printf('n+%'-60s+n', '')printf('|%20s', '$title:')printf('%14s', $value)printf('%26s|n', '')printf('+%'-60s+n', '')};

// 輸出結(jié)果函數(shù)(行形式) function print_line($title, $value); {; printf('%20s', '$title:')printf('%15sn', $value)};

// 排序函數(shù) function my_sort($a, $b); {; return(is_object($a) && is_object($b) ? $b->count - $a->count: 0)};

function start_element($parser, $name, $attrs); {; global $elements, $stack

// 元素是否已在全局$elements數(shù)組中? if(!isset($elements[$name])); {; // 否-增加一個元素的類實(shí)例 $element = new element$elements[$name] = $element};

// 該元素的記數(shù)器加一 $elements[$name]->count++

// 是否有父元素? if(isset($stack[count($stack)-1])); {; // 是-將父元素賦給$last_element $last_element = $stack[count($stack)-1]

// 如果目前元素的父元素?cái)?shù)組為空,初始化為0 if(!isset($elements[$name]->parents[$last_element])); {; $elements[$name]->parents[$last_element] = 0};

// 該元素的父元素記數(shù)器加一 $elements[$name]->parents[$last_element]++

// 如果目前元素的父元素的子元素?cái)?shù)組為空,初始化為0

if(!isset($elements[$last_element]->childs[$name])); {; $elements[$last_element]->childs[$name] = 0};

// 該元素的父元素的子元素記數(shù)器加一 $elements[$last_element]->childs[$name]++};

// 將目前的元素加入到棧中 array_push($stack, $name)};

function stop_element($parser, $name); {; global $stack

// 從棧中將最頂部的元素移去 array_pop($stack)};

function char_data($parser, $data); {; global $elements, $stack, $depth

// 增加目前元素的字符數(shù)目 $elements[$stack][count($stack)-1]]->chars += strlen(trim($data))};

// 產(chǎn)生解析器的實(shí)例 $parser = xml_parser_create()

// 設(shè)置處理函數(shù) xml_set_element_handler($parser, 'start_element', 'stop_element')xml_set_character_data_handler($parser, 'char_data')xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0)

// 解析文件 $ret = xml_parse_from_file($parser, $file)if(!$ret); {; die(sprintf('XML error: %s at line %d',; xml_error_string(xml_get_error_code($parser)),; xml_get_current_line_number($parser)))};

// 釋放解析器 xml_parser_free($parser)

// 釋放協(xié)助元素 unset($elements['current_element'])unset($elements['last_element'])

// 根據(jù)元素的次數(shù)排序 uasort($elements, 'my_sort')

// 在$elements中循環(huán)收集元素信息 while(list($name, $element) = each($elements)); {; print_box('Element name', $name)

print_line('Element count', $element->count)print_line('Character count', $element->chars)

printf('n%20sn', '* Parent elements')

// 在該元素的父中循環(huán),輸出結(jié)果 while(list($key, $value) = each($element->parents)); {; print_line($key, $value)}; if(count($element->parents) == 0); {; printf('%35sn', '[root element]')};

// 在該元素的子中循環(huán),輸出結(jié)果 printf('n%20sn', '* Child elements')while(list($key, $value) = each($element->childs)); {; print_line($key, $value)}; if(count($element->childs) == 0); {; printf('%35sn', '[no childs]')};

$total_elements += $element->count$total_chars += $element->chars};

// 最終結(jié)果 print_box('Total elements', $total_elements)print_box('Total characters', $total_chars)?>

標(biāo)簽: PHP
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲美女91| 亚洲一级淫片| 99久久九九| 亚洲精品乱码| 亚洲人成亚洲精品| 久久久久国产精品一区三寸| 激情视频一区二区三区| 日本一区二区三区视频在线看| 日韩欧美另类一区二区| 欧美视频久久| 成人美女视频| 欧美91精品| 精品欧美日韩精品| 国产 日韩 欧美一区| 日韩国产欧美一区二区| 中文字幕av一区二区三区人 | 亚洲+小说+欧美+激情+另类| 欧美在线观看天堂一区二区三区| 久久精品一区二区不卡| 色综合视频一区二区三区日韩| 日韩va欧美va亚洲va久久| 精品三级久久| 精品亚洲a∨一区二区三区18| 欧美成a人免费观看久久| 99成人超碰| av在线资源| 国产精品一区高清| 欧美日韩一区二区国产 | 私拍精品福利视频在线一区| 国产探花在线精品一区二区| 精品黄色一级片| 亚洲精品第一| 嫩呦国产一区二区三区av| 国产劲爆久久| 91欧美在线| 91久久视频| 久久中文精品| 亚洲激情婷婷| 老牛国内精品亚洲成av人片| 日本а中文在线天堂| 日韩一区精品视频| 国产精品一区亚洲| 欧美理论视频| 国产精品极品国产中出| 久久久久久黄| 免播放器亚洲| 亚洲天堂一区二区| 视频一区二区三区中文字幕| 国产精品亚洲欧美一级在线| 天堂√8在线中文| 亚洲欧美网站在线观看| 麻豆mv在线观看| 久久不见久久见国语| av不卡在线| 99精品综合| 在线一区av| 欧美黑人巨大videos精品| 亚洲一区中文| 亚洲福利专区| 欧美日韩中文一区二区| 亚洲成av在线| 黄色亚洲在线| 国产欧美日韩| 麻豆精品久久久| 国产毛片精品| 成人看片网站| 日韩成人在线看| 一区二区三区四区日本视频| 精品精品99| 日韩精品1区| 日韩高清不卡| 国产精品av久久久久久麻豆网| 精品视频99| 欧美成人aaa| 久久久久伊人| 国产精品欧美在线观看| 久久国产精品免费一区二区三区| 喷白浆一区二区| 99热精品在线观看| 性欧美69xoxoxoxo| 婷婷六月综合| 日韩精品一卡二卡三卡四卡无卡| 午夜欧美精品| 久久夜色精品| 宅男噜噜噜66国产日韩在线观看| 日本欧美在线| 97se亚洲| 麻豆久久一区| 欧美日韩一区二区国产| 日本一区免费网站| 日韩专区欧美专区| 在线看片日韩| 精品国产乱码久久久| 精品高清久久| аⅴ资源天堂资源库在线| 女生影院久久| 日韩精品视频中文字幕| 在线观看一区| 91成人在线网站| 国产欧美丝祙| 国产一区二区三区视频在线| 精品国产亚洲一区二区三区大结局| 精品无人区麻豆乱码久久久| 成人国产精品久久| 亚洲第一区色| av亚洲一区二区三区| 国产精品av一区二区| 亚洲综合电影一区二区三区| 日韩中文字幕| 神马久久午夜| 日日夜夜免费精品视频| 久久av偷拍| 91精品亚洲| 日韩精品一区二区三区中文在线| 麻豆国产精品777777在线| 亚洲性图久久| 久久字幕精品一区| 午夜国产精品视频| 美女毛片一区二区三区四区最新中文字幕亚洲 | 中文字幕一区日韩精品| 成人国产综合| 日韩国产在线一| 国模 一区 二区 三区| 日韩av一区二区在线影视| 免费在线观看精品| 国产一区二区三区四区五区传媒 | 亚洲欧洲美洲av| 97精品资源在线观看| 色欧美自拍视频| 国产探花在线精品一区二区| 亚洲一区成人| 久久蜜桃精品| 国产欧美啪啪| 久久精品午夜| 国产精品观看| 日韩av不卡一区二区| 免费日韩av片| 日本麻豆一区二区三区视频| 日本精品另类| 99视频在线精品国自产拍免费观看| 亚洲精品午夜av福利久久蜜桃| 91欧美国产| 日韩在线欧美| 在线 亚洲欧美在线综合一区| 日本成人手机在线| 美女视频网站久久| 美女视频黄免费的久久| 国产中文字幕一区二区三区| 国产精品极品国产中出| 尤物网精品视频| 国产精品欧美日韩一区| 在线亚洲成人| 国产精品国码视频| 日本韩国欧美超级黄在线观看| 中国女人久久久| 欧美片第1页综合| 精品国产网站| 国精品产品一区| 成人av二区| 青草av.久久免费一区| 精品国产不卡| 人人精品人人爱| 国产欧美日韩在线一区二区 | 日韩激情啪啪| 亚洲性图久久| 国产精品亚洲综合色区韩国| 久久精品国产68国产精品亚洲| 欧美日韩视频一区二区三区| 免费人成网站在线观看欧美高清| 国产精品sss在线观看av| 色爱av综合网| 国产精品日本| 欧美日韩国产v| 国产精品大片免费观看| 福利一区二区三区视频在线观看| 视频一区二区三区在线| 99xxxx成人网| 最新中文字幕在线播放| 蜜臀精品久久久久久蜜臀| 在线精品亚洲| 亚洲一级大片| 精品中文字幕一区二区三区av| 日本午夜精品| 亚洲精品福利| 日韩高清一区在线| 日韩精品网站| 国产一区二区三区四区二区| 视频一区二区三区中文字幕| 日产精品一区二区| 日韩一区精品| 免费看av不卡| 中文字幕亚洲精品乱码| 欧美一区成人| 久久国产影院| 国产精品欧美一区二区三区不卡 | 精品一区二区三区四区五区| 午夜av一区| 亚洲大全视频| 视频一区中文字幕| 午夜精品成人av|