运维开发网
广告位招商联系QQ:123077622
 
广告位招商联系QQ:123077622

ruby – 如何在不知道名称的情况下使用正则表达式为其内容获取XML子标记

运维开发网 https://www.qedev.com 2020-08-09 10:25 出处:网络 作者:运维开发网整理
我简化时看起来像这样的 XML: node_set = Nokogiri::XML(' <PARENT> <SOME_TAG>12:12:1222</SOME_TAG> <HOLY_TAG>12:12:1222</HOLY_TAG> <MAJOR_TAG>12:12:1222</MAJOR_TAG> <FOO_FOO>12:12:1222</FOO_FOO> </PAREN
我简化时看起来像这样的 XML:

node_set = Nokogiri::XML('
<PARENT>
   <SOME_TAG>12:12:1222</SOME_TAG>
   <HOLY_TAG>12:12:1222</HOLY_TAG>
   <MAJOR_TAG>12:12:1222</MAJOR_TAG>
   <FOO_FOO>12:12:1222</FOO_FOO>
</PARENT>'
)

我所知道的只是如何为此写一个正则表达式:

(\d+):(\d+):(\d+)

我在官方网站上阅读了一些关于正则表达式匹配的文章,但没有答案如何做到这一点.只有如何将用户函数调用到xpath方法的机制.

如果不通过regexp知道它的名字,我怎么能得到所有这些标签?

Nokogiri不支持XPath 2.0 matches功能,因此您需要使用Ruby来执行正则表达式:

hits = node_set.xpath("//text()").grep(/\d+:\d+:\d+/).map(&:parent)
p hits.map(&:name)
#=> ["SOME_TAG", "HOLY_TAG", "MAJOR_TAG", "FOO_FOO"]

描述:

>查找整个文档中的所有文本节点.

>将列表缩减为仅匹配所需正则表达式的列表.

>将列表映射到每个文本节点的父元素.

Enumerable#grep方法是.select {| text |的缩写正则表达式=== text}.

或者,请注意您可以定义自己的custom XPath functions in Nokogiri回调Ruby,因此您可以假装使用XPath 2.0匹配:

module FindWithRegex
  def self.matches(nodes,pattern,flags=nil)
    nodes.grep(Regexp.new(pattern,flags))
  end
end

hits = node_set.xpath('//*[matches(text(),"\d+:\d+:\d+")]',FindWithRegex)
p hits.map(&:name)
#=> ["SOME_TAG", "HOLY_TAG", "MAJOR_TAG", "FOO_FOO"]

但是,由于每个找到的节点都重新调用它(因此每次从字符串重新创建一个新的正则表达式),因此效率不高:

require 'benchmark'
Benchmark.bm(15) do |x|
  N = 10000
  x.report('grep and map'){ N.times{
    node_set.xpath("//text()").grep(/\d+:\d+:\d+/).map(&:parent)
  }}
  x.report('custom function'){ N.times{
    node_set.xpath('//*[matches(text(),"\d+:\d+:\d+")]',FindWithRegex)
  }}
end

#=>                      user     system      total        real
#=> grep and map     0.437000   0.016000   0.453000 (  0.442044)
#=> custom function  1.653000   0.031000   1.684000 (  1.694170)

您可以通过缓存正则表达式加快速度:

module FindWithRegex
  REs = {}
  def self.matches(nodes,pattern,flags=nil)
    nodes.grep(REs[pattern] ||= Regexp.new(pattern,flags))
  end
end

#=>                      user     system      total        real
#=> grep and map     0.437000   0.016000   0.453000 (  0.442044)
#=> cached regex     0.905000   0.000000   0.905000 (  0.896090)

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消