提问人:Tim Morton 提问时间:11/12/2015 最后编辑:the Tin ManTim Morton 更新时间:4/25/2017 访问量:104
如何抓取节点并将其作为新对象进行处理
How to grab a node and work on it as a new object
问:
我需要从大型XML文件中提取一个片段,并且只处理该片段。
xml = <<XMLEND
<CFRDOC xsi:noNamespaceSchemaLocation="CFRMergedXML.xsd">
<TITLE>
<SUBTITLE>
<CHAPTER>
<TOC></TOC>
<PART></PART>
<PART></PART>
<PART>
<EAR>Pt. 1903</EAR>
<HD SOURCE="HED">PART 1903—INSPECTIONS, CITATIONS AND PROPOSED PENALTIES</HD>
<CONTENTS></CONTENTS>
<AUTH></AUTH>
<SOURCE></SOURCE>
<SECTION>section1</SECTION>
<SECTION>section2</SECTION>
<SECTION>section3</SECTION>
<SECTION>section4</SECTION>
</PART>
</CHAPTER>
</SUBTITLE>
</TITLE>
</CFRDOC>
XMLEND
doc = Nokogiri::HTML(xml)
section = doc.xpath("//section")
# I can grab a specific node...
section[3].text
=> "section4"
# copy it
temp = section[3].dup
=> #<Nokogiri::XML::Element:0x261ce64 name="section" children=[#<Nokogiri::XML::Text:0x261c98c "section4">]>
# but the variable still refers to the whole...
doc.xpath("//part").size
=> 3
section.xpath("//part").size
=> 3
temp.xpath("//part").size
=> 3
来自PHP背景,我不得不重新考虑变量。我知道 Ruby 中的变量是不同的;它们是指向对象的指针。
因此,当我运行时,我实际上是在运行它。但是我想抓住一个特定的节点及其子节点,然后将其作为新对象进行处理。这将大大缩小大海捞针的范围,并使我的其余工作变得更加轻松!temp.xpath
doc
如何仅使用我选择的节点创建新对象?我想变成一个新对象,它不会看到另一个及其相关标签。section[3]
<part>
<section>
答:
"//part"
意思是“从文档的顶部开始,搜索到底部,找到所有节点。<part>
那不是你想要的。
相反,您需要:
"./part"
这意味着“从当前位置开始并在其中搜索。
最简单的方法是将 XPath 视为在磁盘上导航目录结构。如果要在驱动器的根目录下查找文件,请使用:
/foo
如果您想在当前目录中查找文件,请使用:
./foo
XPath 用来表示“从上到下搜索”://
//foo
我建议使用 CSS 选择器而不是 XPath,除非我需要 XPath 的强大功能。我发现 XPath 在视觉上很嘈杂。所以,相反,我会使用:
section = doc.search('section')
和
section.search('part')
现在,沉思一下:
require 'nokogiri'
xml = <<XMLEND
<CFRDOC xsi:noNamespaceSchemaLocation="CFRMergedXML.xsd">
<TITLE>
<SUBTITLE>
<CHAPTER>
<PART></PART>
<PART>
<SECTION>section1</SECTION>
<SECTION>section2</SECTION>
<SECTION>section3</SECTION>
<SECTION>section4</SECTION>
</PART>
</CHAPTER>
</SUBTITLE>
</TITLE>
</CFRDOC>
XMLEND
doc = Nokogiri::XML(xml)
为了便于阅读,我减少了 XML。
doc.search('SECTION').map(&:text) # => ["section1", "section2", "section3", "section4"]
doc.search('PART').size # => 2
doc.search('PART[2]').text # => "\n section1\n section2\n section3\n section4\n "
doc.search('PART[2]').search('SECTION').map(&:text) # => ["section1", "section2", "section3", "section4"]
doc.search('PART[2] SECTION').map(&:text) # => ["section1", "section2", "section3", "section4"]
doc.search('PART SECTION').map(&:text) # => ["section1", "section2", "section3", "section4"]
使用简单的选择器,可以轻松钻取到文档中。有时不可能编写一个简单的选择器,因此我们必须在文档中找到航点并从中导航,但基于示例 XML 它非常简单。
另请参阅“如何避免在抓取时加入节点中的所有文本”。
评论
//
//
//
doc.search()
Nokogiri::HTML()
Nokogiri::XML()
用于转换回 XML 字符串,然后再次用于获取新对象。to_xml
temp
Nokogiri::XML
my_section = Nokogiri::XML(temp.to_xml)
my_section.xpath('//part').size
# => 0
puts my_section
# <?xml version="1.0"?>
# <section><section4</section>
(我不确定你为什么要开始使用,但如果你认为需要,你可以在这里用它代替。Nokogiri::HTML
XML
评论
Nokogiri::HTML
Nokogiri::XML
Nokogiri::XML
DEFAULT_XML
to_s
to_xml
to_xhtml
to_html
to_s
上一个:Ruby 如何修改参数
评论