首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
中国IT实验室Dotnet频道
中国IT教育
Google
首页 ASP.NET  C#  XML/WebService ADO.NET VC.NET VB.NET .NET 资讯动态 专题 RSS订阅 讨论 下载
您现在的位置: 中国IT实验室 >> Dotnet >> XMLWeb >> 正文

PHP中的XML拉模式详细解析

  该程序仅将响应发送到完整的、格式良好的输入。(也是有效的,不过将实现这点。)因此您需要等待,直到完成了文档的解析(已经跳出 while 循环)。这时,检查是否设置了 $php_errormsg 变量。如果没有进行设置,则文档是格式良好的文档,然后发送 XML-RPC 响应消息。如果设置了该变量,则文档不是格式良好的文档,并发送 XML-RPC 错误响应。如果有人请求负数的平方根,也将发送错误响应。清单 8 展示以上操作。

  清单 8. 检查文档格式是否良好

以下是引用片段:
  // set up the request
  $request = $HTTP_RAW_POST_DATA;
  error_reporting(E_ERROR | E_WARNING | E_PARSE);
  if (isset($php_errormsg)) unset(($php_errormsg);
  // create the reader
  $reader = new XMLReader();
  // $reader->setRelaxNGSchema("request.rng");
  $reader->XML($request);
  $input = "";
  while ($reader->read()) {
  if ($reader->name == "double" && $reader->nodeType == XMLReader::ELEMENT)
 {
  while ($reader->read()) {
  if ($reader->nodeType == XMLReader::TEXT
  || $reader->nodeType == XMLReader::CDATA
  || $reader->nodeType == XMLReader::WHITESPACE
  || $reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE) {
  $input .= $reader->value;
  }
  else if ($reader->nodeType == XMLReader::END_ELEMENT
  && $reader->name == "double") {
  break;
  }
  }
  break;
  }
  }
  // make sure the input was well-formed
  if (isset($php_errormsg) ) fault(21, $php_errormsg);
  else if ($input < 0) fault(20, "Cannot take square root of negative 
number");
  else respond($input);

  这是 XML 流处理中简单的常见模式。解析器将填写一个数据结构,当完成文档时该数据结构将起作用。通常数据结构要比文档本身简单。这里所使用的数据结构尤其简单:一个字符串。

  验证

  到目前为止,对于验证数据是否位于所预期的地方,并没有给予关注。实现该验证的最简单的方法是检查文档的模式。XMLReader 支持 RELAX NG 模式语言;清单 9 展示了简单的 RELAX NG 模式,用于这个特定的 XML-RPC 请求表单。

  libxml 版本

  在 libxml 的早期版本中,RELAX NG 有一些严重错误,XMLReader 取决于 libxml 库。请确保所使用的版本至少是 2.06.26 版。很多系统(包括 Mac OS X Tiger)捆绑了较早的、有错误的 libxml 版本。

  清单 9. XML-RPC 请求

以下是引用片段:
<element name="methodCall" xmlns="http://relaxng.org/ns/structure/1.0" 
 datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <element name="methodName">
    <value>sqrt</value>
  </element>
  <element name="params">
    <element name="param">
      <element name="value">
        <element name="double">
          <data type="double"/>
        </element>
      </element>
    </element>
  </element>
</element>

  可以使用 setRelaxNGSchemaSource() 将模式作为一串文字直接嵌入 PHP 脚本,或者使用 setRelaxNGSchema() 从外部文件或 URL 读取模式。例如,假定清单 9 位于 sqrt.rng 文件中,下面将展示如何载入模式:

以下是引用片段:
reader->setRelaxNGSchema("sqrt.rng")

  在开始解析文档 之前,执行上述操作。解析器在进行读取时将检查文档的模式。若要检查文档是否有效,则调用 isValid(),如果文档是有效的(目前为止),则返回 true,否则,返回 false.清单 10 展示了完整的程序,包括所有错误处理。这样将接受任何合法输入,然后返回正确的值,而且将拒绝所有不正确的请求。我还添加了 fault() 方法,当发生故障时将发送 XML-RPC 错误响应。

  清单 10. 完整的 XML-RPC 平方根服务器

以下是引用片段:
header('Content-type: application/xml');
  // try grammar
  $schema = "
  xmlns='http://relaxng.org/ns/structure/1.0'
  datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'>
  sqrt
  ";
  if (!isset($HTTP_RAW_POST_DATA)) {
  fault(22, "Please make sure always_populate_raw_post_data = On in
 php.ini");
  }
  else {
  // set up the request
  $request = $HTTP_RAW_POST_DATA;
  error_reporting(E_ERROR | E_WARNING | E_PARSE);
  // create the reader
  $reader = new XMLReader();
  $reader->setRelaxNGSchema("request.rng");
  $reader->XML($request);
  $input = "";
  while ($reader->read()) {
  if ($reader->name == "double" && $reader->nodeType == XMLReader::ELEMENT)
 {
  while ($reader->read()) {
  if ($reader->nodeType == XMLReader::TEXT
  || $reader->nodeType == XMLReader::CDATA
  || $reader->nodeType == XMLReader::WHITESPACE
  || $reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE) {
  $input .= $reader->value;
  }
  else if ($reader->nodeType == XMLReader::END_ELEMENT
  && $reader->name == "double") {
  break;
  }
  }
  break;
  }
  }
  if (isset($php_errormsg) ) fault(21, $php_errormsg);
  else if (! $reader->isValid()) fault(19, "Invalid request");
  else if ($input < 0) fault(20, "Cannot take square root of negative 
number");
  else respond($input);
  $reader->close();
  }
  function respond($input)
  {
  ?>
  echo sqrt($input);
  ?>
  }
  function fault($code, $message)
  {
  echo "
  faultCode
  " . $code . "
  faultString
  " . $message . "
  ";
  }

  属性

  在正常的推解析期间不会看到属性。若要读取属性,请停止在元素的起点处,通过名称或编号来请求特定属性。

  将需要的属性名称传递到 getAttribute(),以便在当前元素上查找该属性的值。例如,下面的语句请求当前元素的 id 属性:

以下是引用片段:
$id = $reader->getAttribute("id");

  如果属性位于名称空间中 —— 例如,xlink:href —— 则调用 getAttributeNS(),将本地名称和名称空间 URI 分别作为第一个和第二个参数进行传递。(前缀是无关紧要的。)例如,下面的语句将请求 http://www.w3.org/1999/xlink/ 名称空间中 xlink:href 属性的值:

以下是引用片段:
$href = $reader->getAttributeNS("href", http://www.w3.org/1999/xlink/);

  如果属性不存在,那么这两种方法都将返回空字符串。(这是不正确的。它们应该返回 null.当前设计很难区分值为空字符串的属性和值根本不存在的属性。)

  属性次序

  在 XML 文档中,属性次序并不重要,并且不受解析器的保护。这里用于属性索引的编号仅仅是为了方便起见。不能保证开始标记中的第一个属性就是属性 1,第二个就是属性 2 等等。不要编写依赖于属性次序的代码。

  如果仅希望了解元素上的所有属性,并且事先并不知道属性名,那么当读取器位于元素上时,调用 moveToNextAttribute()。一旦解析器位于属性节点上,就可以读取属性的名称、名称空间以及元素所使用的相同属性的值。例如,以下代码片段将打印当前元素的所有属性:

以下是引用片段:
if ($reader->hasAttributes and $reader->nodeType == XMLReader::ELEMENT) {
  while ($reader->moveToNextAttribute()) {
  echo $reader->name . "='" . $reader->value . "'\n";
  }
  echo "\n";
  }

  对于 XML API 来说非常难得的是,XMLReader 允许从元素的起点 或终点 读取属性。为了避免重复计算,确认代码类型是 XMLReader::ELEMENT 而不是 XMLReader::END_ELEMENT 是很重要的,后者也可能拥有属性。

  结束语

  XMLReader 是添加到 PHP 程序员工具箱中的一个很有用的工具。与 SimpleXML 不同,它是处理所有文档(而不是部分文档)的完整 XML 解析器。与 DOM 不同,它可以处理大于可用内存的文档。与 SAX 不同,它将程序置于控制之下。如果 PHP 程序需要接受 XML 输入,则 XMLReader 是很值得考虑的一个工具。

上一页  [1] [2] [3] 

【责编:John】

中国IT教育

相关产品和培训
文章评论
 友情推荐链接
 认证培训
 专题推荐

 ·WEB程序开发--ASP.NET和PHP、JSP究竟学哪个?
 ·五步带你入门XML
 ·关于Java框架技术专题
 ·XML全攻略技术专题
 ·JAVA开源技术介绍专题
 ·Java嵌入式开发之J2ME技术专题
 ·超前体验 Oracle 11g的5个新特性…
 ·揭密使用VB.NET的五个实用技巧
 ·Oracle和SQL Server常用函数对比专题…
 ·展现C#世界 C#程序设计专题…
 今日更新
 社区讨论
 博客论点
 频道精选
 Dotnet频道相关导航