现在我们将构建一个 Rail 应用程序,并讨论一些有关 Rails 的工作原理、组织构造和使用方法的基本知识,然后将继续介绍 Rails 结合 XML 的使用方法。在 Ruby 中生成和解析 XML 有很多种方法,我们将介绍其中的一小部分,包括 REXML(Ruby Electric XML)、Builder 和 Hpricot(从技术角度来说,Hpricot 是一种 HTML 解析器 —— 但运行速度快,同时也可以处理 XML)。
简介
在过去的 5 到 7 年时间里,XML 成为了应用程序间通信的事实标准(或者至少是事实标准之一)。无论是运行在同一台计算机上的一个应用程序,还是以太网中公开的的一些 Web 服务,抑或是支付网关,运输网关或者其他随机数据源,都需要了解 XML(不管您喜欢与否)。这样说来,撰写这篇教程似乎有些讽刺意味 —— 介绍 Rails 框架上的 XML 处理。不过 Rails 也日渐成名,Loud Thinking 一书中说过:“学习如何使用开源 Web 框架 Rails 轻松愉悦地创建实际应用程序,其所需编写的代码比大多数框架花费在 XML 处理上的还要少。”。这篇教程中所有真正的 XML 处理都不依赖 Rails。所有用到的 XML API 都是直接用 Ruby 编写,并能在任意 Ruby 应用程序中使用。我们将在 Rails 上下文环境中开发 XML API,因为这样可以上传文件以进行处理,并能方便地与编写的代码进行交互。
清单 4. 启动 Rails 应用程序
monkey:~/Work/Rails_XML_Tutorial/xml_tutorial daniel$ ruby script/server
=> Booting lighttpd (use 'script/server webrick' to force WEBrick)
=> Rails application started on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server (see config/lighttpd.conf for options)
有时我们需要把自己的内容呈现给客户机,比如呈现此示例 XML 中生成的一个文件。有时可能是一个 PDF 文档、逗号定界值或者一些其他格式的文件。Rails 只需一小段代码便可以实现这个功能。考察 main_controller.rb 中的方法,它负责把生成的 XML 文件作为下载文件 sample.xml 发回客户机的浏览器(如清单 20 所示)。
清单 21. Rails 控制器类层次结构
ActionController::Base (Part of the Rails framework)| -- ApplicationController (application.rb - generated for you) | -- MainController (main_controller.rb - your controller)
模块和 mixin 不在本文的讨论范围之内,不过可以参阅 参考资料 获得更多有关它们的信息。既然已经有了一些 XML 文档,那就用它们来做点工作吧。
在 Rails 中上传文件(本例使用 XML 文件)
试想一下,这篇教程给您带来的激动吧。您可能按部就班的操作,通过单击一些链接生成示例 XML 文档。您激动万分地向老板展示生成的 XML。可是老板的反应却是失望至极。他对 Fish Head Curry 和 Pig Organ Soup 糟糕的食物评级感到很不解。老板要求您立刻为他构建一个 Web 应用程序,通过该应用程序可以上传 XML 文档并对他所喜欢的食物指定更好的等级。您很幸运,本教程其余部分就是要讨论这个问题。看看如何使用 Rails 上传文件以供处理。
视图代码
考虑到完整性因素,我们简要地看一下处理文件上传表单的视图中的一小段代码(如清单 22 所示)。
清单 22. 用于上传 XML 文档的 RHTML 表单
<% form_tag( {:action => 'upload'}, {:multipart => true} ) do -%>
<%= file_field_tag "xml_file" %> <%= submit_tag "Parse with REXML" %> <%= submit_tag "Parse with Hpricot" %>
<% end -%>
代码使用了标准的 form_tag 和 helper 方法(它是 Rails 框架的一部分),并结合使用了 file_field_tag(用于生成 HTML 文件输入标记)和 submit_tag(用于生成 HTML 提交按钮)。还将使用 submit_tag 调用的值来确定使用控制器中的哪个处理程序来解析上传的 XML 文档。代码不是很漂亮,但很好完成了例子所需的功能。请注意,没有使用模型支持的 helper 标记,因为这篇教程中并没有构建模型。
清单 25. 根据用户输入指定相应的解析方法
def upload uploaded_file = params[:xml_file] data = uploaded_file.read if uploaded_file.respond_to? :read if request.post? and data case params[:commit] when "Parse with REXML" : parse_with_rexml( data ) when "Parse with Hpricot" : parse_with_hpricot( data ) else parse_recursive( data ) end else redirect_to :action => 'index' end end
清单 25 中惟一值得注意的代码段就是新代码的第一行。第一个 if 语句只检查请求是否是 POST 类型(与之相反的是 GET),并确保确实有上传的数据(确保用户确实选取了文件用于上传)。这就完成了!下面我们看看要真正解析和操作这个上传的 XML 文件,需要编写什么样的代码。
解析和操作 XML 文件
既然老板还在为 Fish Head Curry 的分数过低而闷闷不乐,想必您也等不及要继续开发解析和操作 XML 文件的功能。不过同时,从前面的经验我们知道这些 XML API 拥有易于操作的界面。可以着手下一步开发,马上就为那些菜肴评一个高点的分数,让老板高兴起来。
这里的目标是解析上传的 XML 文档,根据需要进行搜索和迭代,找到 Fish Head Curry 和 Pig Organ Soup。,并把它们的等级升级为 6。您希望这样可以让老板面露喜色,不出意外的话,老板会注意到代码的妙处,而不是分数较低的菜肴。
在此特例中,我们要检查元素的文本值,看它是否为 “Fish Head Curry” 或 “Pig Organ Soup”。
清单 27. 检索给定 XML 元素的文本值
if dish_name_element.text == "Fish Head Curry" or dish_name_element.text == "Pig Organ Soup" #... your code here ... #... do work with elements ...end
调用一个 REXML 元素的 text 方法将返回其第一个子文本元素(如果存在的话)的 String 值,不存在则返回零。
清单 30. 使用 REXML 给 XML 元素中的属性指定新值
parent.attributes["rating"] = 6
完成了!已经可以让您的老板高兴了!可以在清单 31 中看一看完整的代码块。
清单 31. 使用 REXML 导航、解析和修改 XML 元素的代码块
XPath.each( doc, "//DishName" ){ |dish_name_element| if dish_name_element.text == "Fish Head Curry" or dish_name_element.text == "Pig Organ Soup" parent = dish_name_element.parent parent.attributes["rating"] = 6 end}
这个时候,您感觉不错,并且在经历了评级失败后希望给老板一个惊喜。于是决定再编写一些用于变更等级的 XML 操作代码片段,这次只使用一行代码。现在您感觉就像是一个 Ruby 的英雄,因此这不值一提(考虑到可读性,可以将代码分成三行)。如清单 32 所示。
清单 32. 解析和操作示例 XML 文档的另一种方法,只使用一行代码
doc.root.each_element( "//DishName" ){ |e| e.parent.attributes["rating"] = 6 unless ["Fish Head Curry", "Pig Organ Soup"].index( e.text ).nil? }
这个方法并没有明确的使用一条 XPath 语句,而是使用的 each_element 方法,该方法是 REXML 的 Element 类的一部分。如果要用一句话来表示这段的意思,从左至右可以这样理解(重要的词语粗体显示):
“找出每个 DishName 元素,如果它的文本是 ‘Pig Organ Soup’ 或 ‘Fish Head Curry’,则把 parent 元素的 rating 属性的值指定为 6”。
接下来我们将介绍使用 Hpricot!
使用 Hpricot 进行解析
从技术角度来说,Hpricot 是一种 HTML 解析器,而不是 XML 解析器,不过由于 HTML 和 XML 使用的语法基本上没什么区别,因此 Hpricot 可以很好地解析发送给它的任何 XML 文档。许多 Ruby 使用者都说 Hpricot 的运行速度(它的扫描器是用 C 语言编写的)比 REXML 快,而且语法也更好,因此他们都选择使用 Hpricot。
使用 Hpricot 解析 XML 时有一点需要注意,如果处理的数据区分大小写,那么有可能产生一些问题。Hpricot 0.5 版(最新发布的)甚至在明确地解析 XML 文档时,也会把所有元素名称都转换成小写。Hpricot Trac (#53) 计划要解决这个问题,不过还没有实现。亲自使用 Hpricot 后您就会对此有所体验了。解析文档和指定新等级的完整代码段非常类似于 REXML(如清单 33 所示)。
清单 33. 使用 Hpricot 解析、导航和操作 XML 文档
def parse_with_hpricot( xml_data ) doc = Hpricot.XML( xml_data ) (doc/:dishname).each{ |dish_name_element| if dish_name_element.inner_html == "Fish Head Curry" or dish_name_element.inner_html == "Pig Organ Soup" parent = dish_name_element.parent parent.attributes["rating"] = "6" end } end
转自于:http://www.iteye.com/problems/23775
问:
我在开发过程中,使用hql进行查询(mysql5)使用到了mysql自带的函数find_in_set()这个函数作为匹配字符串的来讲效率非常好,但是我直接把它写在hql语句里面(from ForumMemberInfo fm,ForumArea fa where find_in_set(fm.userId,f
1、下载软件 rzsz-3.34.tar.gz。登录linux,用命令
wget http://freeware.sgi.com/source/rzsz/rzsz-3.48.tar.gz下载。
2、解压 tar zxvf rzsz-3.34.tar.gz
3、安装 cd rzsz-3.34 ; make posix 。注意:这个软件安装与常规的GNU软件不
Forwarded port
Private network
Public network
Vagrant 中一共有三种网络配置,下面我们将会详解三种网络配置各自优缺点。
端口映射(Forwarded port),顾名思义是指把宿主计算机的端口映射到虚拟机的某一个端口上,访问宿主计算机端口时,请求实际是被转发到虚拟机上指定端口的。Vagrantfile中设定语法为:
c
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or ve