电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

php的xml分析函數

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

首先我得承認我喜歡計算機標準。如果每個人都遵從這個行業的標準,互聯網將會是一個更好的媒體。使用標準化的數據交換格式才能使開放的和獨立于平臺的計算模式切實可行。這就是我作為XML愛好者的原因。

幸運的是,我最喜愛的腳本語言不但支持XML而且對其支持正不斷加強。PHP可以讓我迅速將XML文檔發布到互聯網上,收集XML文檔的統計信息,將XML文檔轉換成其它格式。例如,我時常用PHP的XML處理能力來管理我用XML所寫的文章和書。

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

建立你自己的處理函數; 將XML文檔轉換成你自己的PHP數據結構

介紹Expat

XML的解析器,同樣稱為XML處理器,可以使程序訪問XML文檔的結構和內容。Expat是PHP腳本語言的XML解析器。它同時也運用在其它項目中,例如Mozilla、Apache和Perl。

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

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

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

<greeting>Hello World; </greeting>

基于事件的解析器將報告為三個事件:

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

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

上面Hello-World的范例包括完整的XML格式。但它是無效的,因為既沒有DTD(文檔類型定義)與其聯系,也沒有內嵌DTD。

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

作為不檢查有效性的解析器,Exapt的快速性和輕巧性使其十分適合互聯網程序。

編譯Expat

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

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

XML范例:XMLstats

了解Expat的函數的一個辦法就是通過范例。我們所要討論的范例是使用Expat來收集XML文檔的統計數據。

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

該元素在文檔中使用的次數; 該元素中字符數據的數量; 元素的父元素; 元素的子元素; 注意:為了演示,我們利用PHP來產生一個結構來保存元素的父元素和子元素

準備

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

對象 XML解析函數 描述

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

字符數據 xml_set_character_data_handler() 字符數據的開始

外部實體 xml_set_external_entity_ref_handler() 外部實體出現

未解析外部實體 xml_set_unparsed_entity_decl_handler() 未解析的外部實體出現

處理指令 xml_set_processing_instruction_handler() 處理指令的出現

記法聲明 xml_set_notation_decl_handler() 記法聲明的出現

默認 xml_set_default_handler() 其它沒有指定處理函數的事件

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

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

這個函數需要三個參數:

解析器的實例; 處理開始元素的回調函數的名稱; 處理結束元素的回調函數的名稱; 當開始解析XML文檔時,回調函數必須存在。它們必須定義為與PHP手冊中所描述的原型一致。

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

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

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

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

XML的Case Folding選項

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

解析文檔

在完成所有的準備工作后,現在腳本終于可以解析XML文檔:

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

當解析文檔時,對于Expat需要強調問題的是:如何保持文檔結構的基本描述?

如前所述,基于事件的解析器本身并不產生任何結構信息。

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

為了產生文檔結構的鏡像,腳本至少需要知道目前元素的父元素。用Exapt的API是無法實現的,它只報告目前元素的事件,而沒有任何前后關系的信息。因此,你需要建立自己的棧結構。

腳本范例使用先進后出(FILO)的棧結構。通過一個數組,棧將保存全部的開始元素。對于開始元素處理函數,目前的元素將被array_push()函數推到棧的頂部。相應的,結束元素處理函數通過array_pop()將最頂的元素移走。

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

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

收集數據

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

$count -該元素在文檔中被發現的次數; $chars -元素中字符事件的字節數; $parents -父元素; $childs - 子元素; 正如你所看到的,將類實例保存在數組中是輕而易舉的。

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

當發現一個元素時,我們需要增加其相應的記數器來跟蹤它在文檔中出現多少次。在相應的$elements項中的記數元素也要加一。

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

顯示統計信息

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

腳本范例被設計為通過PHP的CGI方式的命令行來調用。因此,統計結果輸出的格式為文本格式。如果你要將腳本運用到互聯網上,那么你需要修改輸出函數來產生HTML格式。

總結

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

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

提供事件處理函數來處理文檔; 建立自己的事件結構例如棧和樹來獲得XML結構信息標記的優點。; 每天都有新的XML程序出現,而PHP對XML的支持也不斷加強(例如,增加了支持基于DOM的XML解析器LibXML)。

有了PHP和Expat,你就可以為即將出現的有效、開放和獨立于平臺的標準作準備。

范例

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

// 第一個參數是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文件的函數 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)};

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

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

// 排序函數 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數組中? if(!isset($elements[$name])); {; // 否-增加一個元素的類實例 $element = new element$elements[$name] = $element};

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

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

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

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

// 如果目前元素的父元素的子元素數組為空,初始化為0

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

// 該元素的父元素的子元素記數器加一 $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

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

// 產生解析器的實例 $parser = xml_parser_create()

// 設置處理函數 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)

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

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

// 在$elements中循環收集元素信息 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')

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

// 在該元素的子中循環,輸出結果 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};

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

標簽: PHP
主站蜘蛛池模板: 民用音响-拉杆音响-家用音响-ktv专用音响-万昌科技 | 温控器生产厂家-提供温度开关/热保护器定制与批发-惠州市华恺威电子科技有限公司 | 消泡剂-水处理消泡剂-涂料消泡剂-切削液消泡剂价格-东莞德丰消泡剂厂家 | 内窥镜-工业内窥镜厂家【上海修远仪器仪表有限公司】 | 物联网卡_物联网卡购买平台_移动物联网卡办理_移动联通电信流量卡通信模组采购平台? | 跨境物流_美国卡派_中大件运输_尾程派送_海外仓一件代发 - 广州环至美供应链平台 | 上海皓越真空设备有限公司官网-真空炉-真空热压烧结炉-sps放电等离子烧结炉 | 北京网站建设|北京网站开发|北京网站设计|高端做网站公司 | 沧州友城管业有限公司-内外涂塑钢管-大口径螺旋钢管-涂塑螺旋管-保温钢管生产厂家 | 塑胶跑道_学校塑胶跑道_塑胶球场_运动场材料厂家_中国塑胶跑道十大生产厂家_混合型塑胶跑道_透气型塑胶跑道-广东绿晨体育设施有限公司 | 品牌策划-品牌设计-济南之式传媒广告有限公司官网-提供品牌整合丨影视创意丨公关活动丨数字营销丨自媒体运营丨数字营销 | 祝融环境-地源热泵多恒系统高新技术企业,舒适生活环境缔造者! | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | 海外仓系统|国际货代系统|退货换标系统|WMS仓储系统|海豚云 | 【直乐】河北石家庄脊柱侧弯医院_治疗椎间盘突出哪家医院好_骨科脊柱外科专业医院_治疗抽动症/关节病骨伤权威医院|排行-直乐矫形中医医院 | 便民信息网_家电维修,家电清洗,开锁换锁,本地家政公司 | 铁艺,仿竹,竹节,护栏,围栏,篱笆,栅栏,栏杆,护栏网,网围栏,厂家 - 河北稳重金属丝网制品有限公司 山东太阳能路灯厂家-庭院灯生产厂家-济南晟启灯饰有限公司 | 旋振筛|圆形摇摆筛|直线振动筛|滚筒筛|压榨机|河南天众机械设备有限公司 | 今日热点_实时热点_奇闻异事_趣闻趣事_灵异事件 - 奇闻事件 | 水稻烘干机,小麦烘干机,大豆烘干机,玉米烘干机,粮食烘干机_巩义市锦华粮食烘干机械制造有限公司 水环真空泵厂家,2bv真空泵,2be真空泵-淄博真空设备厂 | 中央空调维修、中央空调保养、螺杆压缩机维修-苏州东菱空调 | RTO换向阀_VOC高温阀门_加热炉切断阀_双偏心软密封蝶阀_煤气蝶阀_提升阀-湖北霍科德阀门有限公司 | 科研ELISA试剂盒,酶联免疫检测试剂盒,昆虫_植物ELISA酶免试剂盒-上海仁捷生物科技有限公司 | 糖衣机,除尘式糖衣机,全自动糖衣机,泰州市长江制药机械有限公司 体感VRAR全息沉浸式3D投影多媒体展厅展会游戏互动-万展互动 | 茶叶百科网-茶叶知识与茶文化探讨分享平台| 螺旋丝杆升降机-SWL蜗轮-滚珠丝杆升降机厂家-山东明泰传动机械有限公司 | 黄石东方妇产医院_黄石妇科医院哪家好_黄石无痛人流医院 | 东亚液氮罐-液氮生物容器-乐山市东亚机电工贸有限公司 | 鑫铭东办公家具一站式定制采购-深圳办公家具厂家直销 | 工业洗衣机_工业洗涤设备_上海力净工业洗衣机厂家-洗涤设备首页 bkzzy在职研究生网 - 在职研究生招生信息咨询平台 | 硫酸钡厂家_高光沉淀硫酸钡价格-河南钡丰化工有限公司 | 办公室装修_上海办公室设计装修_时尚办公新主张-后街印象 | 厂房出租_厂房出售_产业园区招商_工业地产&nbsp;-&nbsp;中工招商网 | 高压无油空压机_无油水润滑空压机_水润滑无油螺杆空压机_无油空压机厂家-科普柯超滤(广东)节能科技有限公司 | 承插管件_不锈钢承插管件_锻钢高压管件-温州科正阀门管件有限公司 | 反渗透阻垢剂-缓蚀阻垢剂厂家-循环水处理药剂-山东鲁东环保科技有限公司 | 全自动实验室洗瓶机,移液管|培养皿|进样瓶清洗机,清洗剂-广州摩特伟希尔机械设备有限责任公司 | 健身器材-健身器材厂家专卖-上海七诚健身器材有限公司 | 细砂提取机,隔膜板框泥浆污泥压滤机,螺旋洗砂机设备,轮式洗砂机械,机制砂,圆锥颚式反击式破碎机,振动筛,滚筒筛,喂料机- 上海重睿环保设备有限公司 | 热风机_工业热风机生产厂家上海冠顶公司提供专业热风机图片价格实惠 | 健康管理师报名入口,2025年健康管理师考试时间信息网-网站首页 塑料造粒机「厂家直销」-莱州鑫瑞迪机械有限公司 |