我有一个字符串:
string = <RECALL>first_name</RECALL>, I'd like to send you something. It'll help you learn more about both me and yourself. What is your email?"
我想提取标记<RECALL>
的值“first_name”。
我使用了gem crack
,但它没有按照我的预期行事:
parsed = Crack::XML.parse(string) =>
{"RECALL"=>"first_name, I'd like to send you something. It'll help you learn more about both me and yourself. What is your email?"}
也许XML解析不是正确的方法。我有什么方法可以获得以下所需的行为呢?
{"RECALL"=>"first_name"}
答案 0 :(得分:2)
对我来说看起来不像有效的XML。我会尝试在这里使用REGEXP:
string = "<RECALL>first_name</RECALL>, I'd like to send you something..."
/<RECALL>(.*)<\/RECALL>/.match(string)[1]
#=> "first_name"
答案 1 :(得分:0)
以下两种方法可以获取代码的内容:
string = "<RECALL>first_name</RECALL>"
firstname = string[/<RECALL>([^<]+)</, 1]
firstname # => "first_name"
解析包含标签的字符串变得棘手。它适用于简单的内容,但一旦标记嵌套或出现其他<
或>
,就会变得更加困难。
您可以使用XML解析器使用技巧:
require 'nokogiri'
string = "foo <RECALL>first_name</RECALL> bar"
doc = Nokogiri::XML::DocumentFragment.parse(string)
doc.at('RECALL').text # => "first_name"
请注意,我使用Nokogiri::XML::DocumentFragment.parse
。这告诉Nokogiri只期望部分XML文档,并放宽了许多通常严格的XML规则。然后我可以告诉解析器找到<RECALL>
标记并获取其包含的文本。
...想知道是否有提取方法(我使用Crack来提取它,但只有当
<tag>
位于字符串末尾时它才有效。
此模式匹配mid-string:
str = "foo <RECALL>first_name</RECALL> bar"
str[%r!<RECALL>([^<]+)</RECALL>!, 1] # => "first_name"
如果标签不在字符串的末尾,则此模式失败:
str[%r!<RECALL>([^<]+)</RECALL>\z!, 1] # => nil
如果它在字符串的末尾,则成功:
str = "foo <RECALL>first_name</RECALL>"
str[%r!<RECALL>([^<]+)</RECALL>\z!, 1] # => "first_name"
这是一个正则表达式模式比使用解析器更容易做事的地方。
使用解析器:
require 'nokogiri'
通常我们不关心标签在DOM中的位置,但如果它很重要,我们可以弄清楚它与其他标签的关系。尽管如此,它永远不会那么简单:
如果标签不在字符串/ DOM的末尾,则返回nil
:
str = "foo <RECALL>first_name</RECALL> bar"
doc = Nokogiri::XML::DocumentFragment.parse(str)
recall_node = doc.at('RECALL')
recall_node == doc.children.last ? doc.at('RECALL').text : nil # => nil
这将返回节点的文本,因为它位于DOM的末尾:
str = "foo <RECALL>first_name</RECALL>"
doc = Nokogiri::XML::DocumentFragment.parse(str)
recall_node = doc.at('RECALL')
recall_node == doc.children.last ? doc.at('RECALL').text : nil # => "first_name"
这是有效的,因为文档中的每个节点都有一个标识符,我们可以询问感兴趣的节点是否与DOM中的最后一个节点匹配:
require 'nokogiri'
doc = Nokogiri::XML::DocumentFragment.parse("<node>first_name</node> text")
# => #(DocumentFragment:0x3ffc89c3d3e8 {
# name = "#document-fragment",
# children = [
# #(Element:0x3ffc89c3cf9c {
# name = "node",
# children = [ #(Text "first_name")]
# }),
# #(Text " text")]
# })
doc.at('node').object_id.to_s(16) # => "3ffc89c3cf9c"
doc.children.last.object_id.to_s(16) # => "3ffc89c3cec0"
doc = Nokogiri::XML::DocumentFragment.parse("<node>first_name</node>")
# => #(DocumentFragment:0x3ffc89c345cc {
# name = "#document-fragment",
# children = [
# #(Element:0x3ffc89c342c0 {
# name = "node",
# children = [ #(Text "first_name")]
# })]
# })
doc.at('node').object_id.to_s(16) # => "3ffc89c342c0"
doc.children.last.object_id.to_s(16) # => "3ffc89c342c0"