|
PHP中的XML拉模式解析(3) echo $reader->name; if ($reader->hasValue) { echo ": " . $reader->value; } echo "\n"; }
清单 4. 清单 3 的输出
methodCall #text: methodName #text: sqrt methodName #text: params #text: param #text: value double #text: 10 double value #text: param #text: params #text: methodCall
大多数程序并非这么简单。它们接受特定格式的输入,并以某种方式来处理输入。在 XML-RPC 例子中,仅需要读取输入中的一个元素:double 元素,该元素应该只有一个。为此,查找名称为 double 的元素的起点:
if ($reader->name == "double" && $reader->nodeType == XMLReader::ELEMENT) { // ... }
该元素可能有单个文本子节点,可以通过将解析器前进到下一个节点来进行读取,如下所示:
if ($reader->name == "double" && $reader->nodeType == XMLReader::ELEMENT) { $reader->read(); respond($reader->value); }
在这里 respond() 函数构建了 XML-RPC 响应并将它发送到客户机。但是,在展示上述操作前,还有一些事情需要处理。不能绝对保证请求文档中的 double 元素仅包含一个文本节点。可能包含多个文本节点,以及注释和处理指令。例如,可能看起来像以下代码:
<value><double> <!--value follows-->6.<!--fractional part next-->0 </double></value>
嵌套元素
该模式存在一个潜在的缺陷。嵌套的 double 元素(例如 61.2)将违背该算法。然而它将成为无效的 XML-RPC;并且不久您将看到如何使用 RELAX NG 验证来拒绝所有此类文档。在诸如可扩展超文本标记语言(Extensible Hypertext Markup Language,XHTML)之类的文档类型中,允许相同元素互相包含(例如 table 元素包含在另一个 table 元素中),因此您还需要知道元素的深度,从而确保结束标记与开始标记之间进行正确匹配。
一个健壮的解决方案需要获得 double 元素的所有文本子节点,将它们连接起来,并且仅将结果转换为 double。必须小心避免任何注释或可能出现的其它非文本节点。这有一点复杂,但并不是十分复杂,如清单 5 所示。
清单 5. 累积来自一个元素的所有文本内容
while ($reader->read()) {
|