Should Nokogiri::XML.parse be creating separate Te

2019-08-09 00:47发布

I have an XML document created by an outside tool:

<?xml version="1.0" encoding="UTF-8"?>
<suite>
  <id>S1</id>
  <name>First Suite</name>
  <description></description>
  <sections>
    <section>
  <name>section 1</name>                    
      <cases>
        <case>
          <id>C1</id>
          <title>Test 1.1</title>
          <type>Other</type>
          <priority>4 - Must Test</priority>
          <estimate></estimate>
          <milestone></milestone> 
          <references></references> 
        </case>                             
        <case>
          <id>C2</id>
          <title>Test 1.2</title>
          <type>Other</type>
          <priority>4 - Must Test</priority>
          <estimate></estimate>
          <milestone></milestone> 
          <references></references> 
        </case>
      </cases>
    </section>
  </sections>
</suite>

From irb, I do the following: (Output suppressed until final command)

> require('nokogiri')
> doc = Nokogiri::XML.parse(open('./test.xml'))
> test_case = doc.search('case').first
=> #<Nokogiri::XML::Element:0x3ff75851bc44 name="case" children=[#<Nokogiri::XML::Text:0x3ff75851b8fc "\n          ">, #<Nokogiri::XML::Element:0x3ff75851b7bc name="id" children=[#<Nokogiri::XML::Text:0x3ff75851b474 "C1">]>, #<Nokogiri::XML::Text:0x3ff75851b1cc "\n          ">, #<Nokogiri::XML::Element:0x3ff75851b078 name="title" children=[#<Nokogiri::XML::Text:0x3ff75851ad58 "Test 1.1">]>, #<Nokogiri::XML::Text:0x3ff75851aa9c "\n          ">, #<Nokogiri::XML::Element:0x3ff75851a970 name="type" children=[#<Nokogiri::XML::Text:0x3ff75851a6c8 "Other">]>, #<Nokogiri::XML::Text:0x3ff7585191d8 "\n          ">, #<Nokogiri::XML::Element:0x3ff7585190d4 name="priority" children=[#<Nokogiri::XML::Text:0x3ff758518d64 "4 - Must Test">]>, #<Nokogiri::XML::Text:0x3ff758518ad0 "\n          ">, #<Nokogiri::XML::Element:0x3ff7585189a4 name="estimate">, #<Nokogiri::XML::Text:0x3ff758518670 "\n          ">, #<Nokogiri::XML::Element:0x3ff758518558 name="milestone">, #<Nokogiri::XML::Text:0x3ff7585182b0 "\n          ">, #<Nokogiri::XML::Element:0x3ff758518184 name="references">, #<Nokogiri::XML::Text:0x3ff758517ef0 "\n        ">]>

This results in a number of children that look like the following:

#<Nokogiri::XML::Text:0x3ff758517ef0 "\n        ">

I want to iterate through these XML nodes without having to do something like:

> real_nodes = test_case.children.reject{|n| n.node_name == 'text' && n.content.strip!.empty?}

I couldn't find a parse parameter in the Nokogiri docs to suppress the treating of newlines as separate nodes. Is there a way to do this during the parse instead of after?

2条回答
闹够了就滚
2楼-- · 2019-08-09 01:28

The text nodes are the result of pretty-printing the XML. The spec doesn't require whitespace between tags, and, for efficiency, a huge XML file could be stripped of inter-tag whitespace to save space and reduce transfer time, without sacrificing the data content.

This might show what's happening:

require 'nokogiri'

xml = '<foo></foo>'
Nokogiri::XML(xml).at('foo').child
=> nil

With no whitespace between the tags there's no text node either.

xml = '<foo>
</foo>'
Nokogiri::XML(xml).at('foo').child
=> #<Nokogiri::XML::Text:0x3fcee9436ff0 "\n">
doc.at('foo').child.class
=> Nokogiri::XML::Text

With whitespace for pretty-printing, the XML has a text node following the foo tag.

查看更多
做个烂人
3楼-- · 2019-08-09 01:28

Check the documentation. You can just do this:

doc = Nokogiri::XML.parse(open('./test.xml')) do |config|
    config.noblanks
end

That will load the file without any empty nodes.

查看更多
登录 后发表回答