A coroutine example: Streaming XML parsing using xml_parser


<?php

error_reporting(E_ALL);

/* Data can be send to coroutines using `$coroutine->send($data)`. The sent data will then
* be the result of the `yield` expression. Thus it can be received using a code like
* `$data = yield;`.
*/

/* What we‘re building in this script is a coroutine-based streaming XML parser. The PHP
* extension for parsing streamed XML is xml_parser. It is used by defining a set of
* callback functions for various events (like start tag, end tag, content).
*
* This event model makes the parsing process very complicated, because you basically
* have to implement your own state machine (which is a lot of boilerplate code the
* more complicated the XML gets).
*
* To solve this problem, we build a wrapper (the following function), which redirects
* the events to a coroutine ($target). This is done simply using
* `$target->send([$eventName, $data])`.
*/
function streamingXMLParser($target) {
$xmlParser = xml_parser_create();
xml_set_element_handler(
$xmlParser,
function ($xmlParser, $name, array $attributes) use ($target) {
$target->send([‘start‘, [$name, $attributes]]);
},
function ($xmlParser, $name) use ($target) {
$target->send([‘end‘, $name]);
}
);
xml_set_character_data_handler(
$xmlParser,
function ($xmlParser, $text) use ($target) {
$target->send([‘text‘, $text]);
}
);

while ($data = yield) {
if (!xml_parse($xmlParser, $data)) {
throw new Exception(sprintf(
‘XML error "%s" on line %d‘,
xml_error_string(xml_get_error_code($xmlParser)),
xml_get_current_line_number($xmlParser)
));
}
}

xml_parser_free($xmlParser);
}

/* Inside the target coroutine the actual parsing happens. The events are received
* using `list($event, $data) = yield`. The main advantage that coroutines bring
* here is that you can fetch the events in nested loops. This way you are implicitly
* building a state machine (but the state is managed by PHP, not you!)
*
* This particular coroutine parses bus location data (for samples scroll down). The
* result is passed to another $target coroutine.
*/
function busXMLParser($target) {
while (true) {
list($event, $data) = yield;
if ($event == ‘start‘ && $data[0] == ‘BUS‘) {
$dict = [];
$content = ‘‘;
while (true) {
list($event, $data) = yield;
if ($event == ‘start‘) {
$content = ‘‘;
} elseif ($event == ‘text‘) {
$content .= $data;
} elseif ($event == ‘end‘) {
if ($data == ‘BUS‘) {
$target->send($dict);
break;
}

$dict[strtolower($data)] = $content;
}
}
}
}
}

/* This coroutine prints out the info it receives from the bus XML parser. */
function busLocationPrinter() {
while (true) {
$data = yield;
echo "Bus $data[id] is currently at $data[latitude]/$data[longitude]\n";
}
}

/* Here we are building up a coroutine pipeline. You should read this as:
* The streaming XML parser is passing data to the bus XML parser, which
* is passing data to the bus location printer.
*/
$parser = streamingXMLParser(busXMLParser(busLocationPrinter()));

/* I don‘t have access to a real bus location API, so I‘ll just stream some
* fictional sample data */
$parser->send(‘<?xml version="1.0"?><buses>‘);
while (true) {
sleep(1);
$parser->send(sprintf(
‘<bus><id>%d</id><latitude>%f</latitude><longitude>%f</longitude></bus>‘,
mt_rand(1, 1000), lcg_value(), lcg_value()
));
}

/* If your head is buzzing now, that‘s a good thing :P */

A coroutine example: Streaming XML parsing using
xml_parser

时间: 2024-11-08 17:58:52

A coroutine example: Streaming XML parsing using xml_parser的相关文章

【Java】Java XML 技术专题

XML 基础教程 XML 和 Java 技术 Java XML文档模型 JAXP(Java API for XML Parsing) StAX(Streaming API for XML) XJ(XML Enhancements for Java) XML 验证 XPath XQuery XSL 转换处理器 XStream 数据绑定 本专题汇总了大量面向 Java 开发人员的 XML 技术文章和教程,内容涉及 XML 基础.Java XML 的文档模型.编程 API 与数据绑定框架以及 Java

XML(七)-DOM解析

DOM解析 JAXP(Java API for XML Parsing) :用于XML解析的Java API. 本文通过一个实际的代码例子来说明如何用Java提供的DOM相关的类和接口解析XML: 首先,是XML文档:persons.xml <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE persons [ <!ENTITY xx &quo

json数据相对于xml数据.

JSON is a valid subset of JavaScript, Python, and YAML JSON parsing is generally faster than XML parsing. JSON is a more compact format, meaning it weighs far less on the wire than the more verbose XML. JSON is easier to work with in some languages (

XML解析简介及Xerces-C++简单使用举例

XML是由World WideWeb联盟(W3C)定义的元语言.它已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便.XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已. XML本身只是以纯文本对数据进行编码的一种格式,要想利用XML,或者说利用XML文件中所编码的数据,必须先将数据从纯文本中解析出来,因此,必须有一个能够识别XML文档中信息的解析器,用来解释XML文档并提取其中的数据.然而,根据数据提取的不同需求,又存在着多种

(轉載)sql server xml字段的操作

原文轉自:http://blog.csdn.net/hliq5399/article/details/8315373 今天用到sql server 的xml字段,首先这个项目中的xml字段都存为了ntext字段,所以第一个操作 ntext 转化为 xml 以下摘自 http://blog.darkthread.net/blogs/darkthreadtw/archive/2008/09/18/sql2005-nvarchar-to-xml.aspx XmlString是一個NText欄位,裡面放

基于事件的XML解析【使用解析器】(中国天气网)

参考 :php手册 (XML 元素结构例程) <?php header("content-type:text/html;charset=utf-8"); //接口URL. $file='http://flash.weather.com.cn/wmaps/xml/china.xml'; $result = array();//定义全局变量 function startTag($parser, $name, $attrs) { global $result; $array=array

js与xml交互理论和示例

---------------------------------------------------js+xml--------------------------------------------------------------------------- DOM2级在 document.implementation 中引入了 createDocument() 方法. IE9+. Firefox. Opera. Chrome 和 Safari 都支持这个方法. 想一想, 或许你还记得可以

Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(上

                                                                                                                                               本文原创, 转载请注明出处:http://blog.csdn.net/qinjuning 在之前一篇博文中<<Android中View绘制流程以及invalidate()等相关方法分析>>,简单的阐述

js解析xml浏览器兼容性处理

1 /****************************************************************************** 2 说明:xml解析类 3 ******************************************************************************/ 4 5 6 function XMLDOCDocument() { 7 this.xmlDoc = null; 8 this.async = fal