Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何获得兄弟姐妹';根据特定定义的兄弟内容的子级_Ruby_Xml_Nokogiri - Fatal编程技术网

Ruby 如何获得兄弟姐妹';根据特定定义的兄弟内容的子级

Ruby 如何获得兄弟姐妹';根据特定定义的兄弟内容的子级,ruby,xml,nokogiri,Ruby,Xml,Nokogiri,我需要找到从以下XML数据中收集作家和艺术家信息的最佳方法。漫画节点出现多次,并包含单个漫画书的数据 我无法根据他们的工作职能、作家、艺术家等找到合适的人选。有时,每本漫画书都有多个作家和艺术家。我的计划是把每一个都添加到一个列表中 因此,对于这本漫画书,我需要获取所有作者和艺术家的显示名称,但作业功能(例如writer)是人名的兄弟 以下是我拥有的,但不起作用: writer = [] penciler = [] doc.xpath('//comic').each do |main_eleme

我需要找到从以下XML数据中收集作家和艺术家信息的最佳方法。
漫画
节点出现多次,并包含单个漫画书的数据

我无法根据他们的工作职能、作家、艺术家等找到合适的人选。有时,每本漫画书都有多个作家和艺术家。我的计划是把每一个都添加到一个列表中

因此,对于这本漫画书,我需要获取所有作者和艺术家的显示名称,但作业功能(例如writer)是人名的兄弟

以下是我拥有的,但不起作用:

writer = []
penciler = []
doc.xpath('//comic').each do |main_element|
 main_element.xpath("mainsection/credits/credit/role[@id='dfWriter']").each do |n|
    writer << n.xpath('person/displayname').text
  end
  main_element.xpath("mainsection/credits/credit/role[@id='dfPenciler']").each do |n|
    penciler << n.xpath('person/displayname').text
  end
end

p "Writer(s): ",writer
p "Penciler(s): ",penciler
如果目标元素始终位于
角色之后,则可以使用XPath axis实现此目的:

doc.xpath('//comic').each do |main_element|
 main_element.xpath("mainsection/credits/credit/role[@id='dfWriter']").each do |n|
    writer << n.xpath('following-sibling::person/displayname').text
  end
  main_element.xpath("mainsection/credits/credit/role[@id='dfPenciler']").each do |n|
    penciler << n.xpath('following-sibling::person/displayname').text
  end
end

下面是我如何着手做这件事:

require 'nokogiri'

XML = <<EOT
<comic>
  <mainsection>
    <credits>
      <credit>
        <role id="dfWriter">Writer</role>
        <person>
          <displayname>Will Pfeifer</displayname>
        </person>
      </credit>
      <credit>
        <role id="dfWriter">Writer</role>
        <person>
          <displayname>John Byrne</displayname>
        </person>
      </credit>
      <credit>
        <role id="dfPenciler">Penciller</role>
        <person>
          <displayname>John Byrne</displayname>
        </person>
      </credit>
    </credits>
  </mainsection>
</comic>
EOT

doc = Nokogiri::XML(XML)

writers = doc.search("credits role[id='dfWriter']").map { |w| w.parent.at('displayname').text }
pencilers = doc.search("credits role[id='dfPenciler']").map { |n| n.parent.at('displayname').text }

puts "Writer(s): %s" % writers.join(', ')
puts "Penciler(s): %s" % pencilers.join(', ')

# >> Writer(s): Will Pfeifer, John Byrne
# >> Penciler(s): John Byrne
这:

可干燥至:

writers, pencilers = %w(dfWriter dfPenciler).map { |s|
  doc.search("credits role[id='#{s}']").map { |w| w.parent.at('displayname').text }
}
为了可读性,我使用了CSS,当我需要文本时,
at
返回一个节点,而不是
xpath
,后者返回一个节点集

在节点集上使用
text
与在节点上使用
之间的区别非常重要。考虑这一点:

require 'nokogiri'

xml = <<EOT
<root>
  <displayname>Will Pfeifer</displayname>
  <displayname>John Byrne</displayname>
  <displayname>John Byrne</displayname>
</root>
EOT

doc = Nokogiri::XML(xml)
doc.search('displayname').class # => Nokogiri::XML::NodeSet
doc.search('displayname').text # => "Will PfeiferJohn ByrneJohn Byrne"

doc.at('displayname').class # => Nokogiri::XML::Element
doc.at('displayname').text # => "Will Pfeifer"

谢谢。这正是我想要的。对于这些问题,您有什么推荐的阅读资料吗?学习XPath。我先是,然后是。在XPath测试仪(比如or)中大量使用XPath,我没有意识到XPath有多像野兽。ThanksNokogiri让我们有充分的理由使用XPath和CSS。CSS更易于阅读,并且与处理HTML有很好的关系,但是CSS也缺乏XPath所具有的深度,因此学习两者都是很好的。为了可读性,我建议使用CSS,只有在需要特定功能时才跳到XPath。XML似乎与您的代码不一致。您将
comic
显示为根节点,但是
//comic
不是我们搜索的方式。
require 'nokogiri'

XML = <<EOT
<comic>
  <mainsection>
    <credits>
      <credit>
        <role id="dfWriter">Writer</role>
        <person>
          <displayname>Will Pfeifer</displayname>
        </person>
      </credit>
      <credit>
        <role id="dfWriter">Writer</role>
        <person>
          <displayname>John Byrne</displayname>
        </person>
      </credit>
      <credit>
        <role id="dfPenciler">Penciller</role>
        <person>
          <displayname>John Byrne</displayname>
        </person>
      </credit>
    </credits>
  </mainsection>
</comic>
EOT

doc = Nokogiri::XML(XML)

writers = doc.search("credits role[id='dfWriter']").map { |w| w.parent.at('displayname').text }
pencilers = doc.search("credits role[id='dfPenciler']").map { |n| n.parent.at('displayname').text }

puts "Writer(s): %s" % writers.join(', ')
puts "Penciler(s): %s" % pencilers.join(', ')

# >> Writer(s): Will Pfeifer, John Byrne
# >> Penciler(s): John Byrne
# >> Writer(s): Will Pfeifer, John Byrne
# >> Penciler(s): John Byrne
writers = doc.search("credits role[id='dfWriter']").map { |w| w.parent.at('displayname').text }
pencilers = doc.search("credits role[id='dfPenciler']").map { |n| n.parent.at('displayname').text }
writers, pencilers = %w(dfWriter dfPenciler).map { |s|
  doc.search("credits role[id='#{s}']").map { |w| w.parent.at('displayname').text }
}
require 'nokogiri'

xml = <<EOT
<root>
  <displayname>Will Pfeifer</displayname>
  <displayname>John Byrne</displayname>
  <displayname>John Byrne</displayname>
</root>
EOT

doc = Nokogiri::XML(xml)
doc.search('displayname').class # => Nokogiri::XML::NodeSet
doc.search('displayname').text # => "Will PfeiferJohn ByrneJohn Byrne"

doc.at('displayname').class # => Nokogiri::XML::Element
doc.at('displayname').text # => "Will Pfeifer"
doc.search('displayname').map(&:text) # => ["Will Pfeifer", "John Byrne", "John Byrne"]