Получить дочерние элементы без текстовых узлов - PullRequest
9 голосов
/ 15 февраля 2012

Я использую Nokogiri с Ruby для интерпретации содержимого файла XML. Я хотел бы получить массив (или аналогичный) всех элементов, которые являются прямыми потомками <where> в моем примере. Однако я получаю различные текстовые узлы (например, "\n\t\t\t"), которые мне не нужны. Есть ли способ, которым я могу удалить или игнорировать их?

@body = "
<xml>
  <request>
    <where>
      <username compare='e'>Admin</username>
      <rank compare='gt'>5</rank>
    </where>
  </request>
</xml>" #in my code, the XML contains tab-indentation, rather than spaces. It is edited here for display purposes.

@noko = Nokogiri::XML(@body)
xml_request = @noko.xpath("//xml/request")
where = xml_request.xpath("where")
c = where.children
p c

Вышеприведенные сценарии Ruby:

[#<Nokogiri::XML::Text:0x100344c "\n\t\t\t">, #<Nokogiri::XML::Element:0x1003350 name="username" attributes=[#<Nokogiri::XML::Attr:0x10032fc name="compare" value="e">] children=[#<Nokogiri::XML::Text:0x1007580 "Admin">]>, #<Nokogiri::XML::Text:0x100734c "\n\t\t\t">, #<Nokogiri::XML::Element:0x100722c name="rank" attributes=[#<Nokogiri::XML::Attr:0x10071d8 name="compare" value="gt">] children=[#<Nokogiri::XML::Text:0x1006cec "5">]>, #<Nokogiri::XML::Text:0x10068a8 "\n\t\t">]

Я хотел бы как-нибудь получить следующий объект:

[#<Nokogiri::XML::Element:0x1003350 name="username" attributes=[#<Nokogiri::XML::Attr:0x10032fc name="compare" value="e">] children=[#<Nokogiri::XML::Text:0x1007580 "Admin">]>, #Nokogiri::XML::Element:0x100722c name="rank" attributes=[#<Nokogiri::XML::Attr:0x10071d8 name="compare" value="gt">] children=[#<Nokogiri::XML::Text:0x1006cec "5">]>]

В настоящее время я могу обойти эту проблему, используя

c.each{|child|
  if !child.text?
    ...
  end
}

но c.length == 5. Будет проще, если кто-нибудь подскажет, как исключить прямые дочерние текстовые узлы из c, чтобы c.length == 2

1 Ответ

14 голосов
/ 15 февраля 2012

У вас есть (как минимум) три варианта на выбор:

  1. Используйте c = where.element_children вместо c = where.children.

  2. Выберите только дочерние элементы напрямую:
    c = xml_request.xpath('./where/*') или
    c = where.xpath('./*')

  3. Отфильтровать список дочерних элементов к только тем, которые являются элементами :
    c = where.children.select(&:element?)

...