<?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的更多相关文章

  1. Dreamweaver无法启动:xml parsing fatal error..Designer.xml错误解决方法

    xml parsing fatal error:Invalid document structure,line:1,file:C:\Documents and Settings\Administrat ...

  2. XML Parsing Error: no element found Location: moz-nullprincipal:{23686e7a-652b-4348-92f4-7fb3575179ed} Line Number 1, Column 1:^

    “Hi Insus.NET, 我有参考你下午发布的一篇<jQuery.Ajax()执行WCF Service的方法>http://www.cnblogs.com/insus/p/37278 ...

  3. 解决org.apache.jasper.JasperException: org.apache.jasper.JasperException: XML parsing error on file org.apache.tomcat.util.scan.MergedWebXml

    1.解决办法整个项目建立时采用utf-8编码,包括代码.jsp.配置文件 2.并用最新的tomcat7.0.75 相关链接: http://ask.csdn.net/questions/223650

  4. Parsing XML in J2ME

    sun的原文,原文地址是http://developers.sun.com/mobility/midp/articles/parsingxml/. by Jonathan KnudsenMarch 7 ...

  5. 【Java】Java XML 技术专题

    XML 基础教程 XML 和 Java 技术 Java XML文档模型 JAXP(Java API for XML Parsing) StAX(Streaming API for XML) XJ(XM ...

  6. iphone Dev 开发实例8: Parsing an RSS Feed Using NSXMLParser

    From : http://useyourloaf.com/blog/2010/10/16/parsing-an-rss-feed-using-nsxmlparser.html Structure o ...

  7. php判断字符串是不是xml格式并解析

    最近遇到要要判断一个字符串是不是xml格式,网上找到一段代码,试了一下,完全可行 /**      * 解析XML格式的字符串      *      * @param string $str     ...

  8. Java解析XML文档(简单实例)——dom解析xml

      一.前言 用Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple API for XML)称为SAX和基于树和节点的文档对象模型(Document Object ...

  9. javascript-处理XML

    /** * Created by Administrator on 2015/4/4. */ var XmlUtil=(function () { var createDocument= functi ...

随机推荐

  1. 通过C#来加载X509格式证书文件并生成RSA对象

    private static RSACryptoServiceProvider GetPrivateKey(string priKeyFile, string keyPwd) { var pc = n ...

  2. [Android] 建立与使用Library

    [Android] 建立与使用Library 前言 使用Eclipse开发Android项目时,开发人员可以将可重用的程序代码,封装为Library来提供其他开发人员使用.本篇文章介绍如何将可重用的程 ...

  3. #8.10.16总结# 属性选择符 伪对象选择符 CSS的常用样式

    属性选择符 E[att] E[att="val"] E[att~="val"] E[att^="val"] E[att$="val ...

  4. javscript闭包的准备工作 -- 作用域与作用域链

    作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望 ...

  5. iOS 3DES加密解密(一行代码搞定)

    3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称.它相当于是对每个数据块应用三次DES加密算法.由于计 ...

  6. ABAP中的同步和异步调用

    ABAP 的 CALL FUNCTION 类似于 Java/.NET 中的本地或远程方法调用.CALL FUNCTION 可以分为四种:1. Synchronous RFC (sRFC) - 同步调用 ...

  7. ae_datagridview显示属性

    public partial class FrmAttributeTable : Form { private AxMapControl m_MapCtl; public FrmAttributeTa ...

  8. 将数据导入PostGIS

    #!/usr/bin/env python # -*- coding: utf-8 -*- import subprocess # database options db_schema = " ...

  9. [SharePoint] SharePoint 错误集 1

    1. Delete a site collection · Run command : Remove-SPSite –Identity http://ent132.sharepoint.hp.com/ ...

  10. select count(*)和select count(1)

    一般情况下,Select Count (*)和Select Count(1)两着返回结果是一样的 假如表沒有主键(Primary key), 那么count(1)比count(*)快, 如果有主键的話 ...