Skip to content

[bug] calling .attr on a NodeSet returns nil in 1.18 #3487

@navarone-feekery

Description

@navarone-feekery

Please describe the bug

According to the documentation for NodeSet, calling .attr on a NodeSet should return the attribute of the first Node in the set.

Set attributes on each Node in the NodeSet, or get an attribute from the first Node in the NodeSet.

This is how the code functioned in 1.16.8. However, after upgrading to 1.18.5, .attr returns nil. To get the first Node I am having to call .first before .attr.

I think this is either a bug, or the documentation needs to be updated to reflect the newer usage.

Help us reproduce what you're seeing

Example usage with nil output

Nokogiri::HTML('<meta name="keywords" content="keywords, stuffing, SEO" />').css('meta[name=keywords]')
=> [#<Nokogiri::XML::Element:0xfd8 name="meta" attribute_nodes=[#<Nokogiri::XML::Attr:0xfd0 name="content" value="keywords, stuffing, SEO">, #<Nokogiri::XML::Attr:0xfd4 name="name" value="keywords">]>]

Nokogiri::HTML('<meta name="keywords" content="keywords, stuffing, SEO" />').css('meta[name=keywords]')&.attr('content')
=> nil

Nokogiri::HTML('<meta name="keywords" content="keywords, stuffing, SEO" />').css('meta[name=keywords]').first&.attr('content')
=> "keywords, stuffing, SEO"

Example of how I was fetching the same value, but in 1.16.8 (this worked before upgrading to 1.18.5). In this version I was also calling .content on the .attr.

Nokogiri::HTML('<meta name="keywords" content="keywords, stuffing, SEO" />').css('meta[name=keywords]')
=> [#<Nokogiri::XML::Element:0xfe4 name="meta" attribute_nodes=[#<Nokogiri::XML::Attr:0xfdc name="content" value="keywords, stuffing, SEO">, #<Nokogiri::XML::Attr:0xfe0 name="name" value="keywords">]>]

Nokogiri::HTML('<meta name="keywords" content="keywords, stuffing, SEO" />').css('meta[name=keywords]')&.attr('content')
=> #(Attr:0xfe8 { name = "content", value = "keywords, stuffing, SEO" })

Nokogiri::HTML('<meta name="keywords" content="keywords, stuffing, SEO" />').css('meta[name=keywords]')&.attr('content')&.content
=> "keywords, stuffing, SEO"

Expected behavior

Either:

a. Calling .attr on a NodeSet operates on the first Node in that set, or
b. The documentation reflects that .attr can't be called on a NodeSet anymore

Environment

# Nokogiri (1.18.5)
    ---
    warnings: []
    nokogiri:
      version: 1.18.5
    ruby:
      version: 3.1.4
      platform: java
      gem_platform: universal-java-23
      description: jruby 9.4.7.0 (3.1.4) 2024-04-29 597ff08ac1 OpenJDK 64-Bit Server VM
        23.0.2 on 23.0.2 +jit [arm64-darwin]
      engine: jruby
      jruby: 9.4.7.0
    other_libraries:
      isorelax:isorelax: '20030108'
      net.sf.saxon:Saxon-HE: 9.6.0-4
      net.sourceforge.htmlunit:neko-htmlunit: 2.63.0
      nu.validator:jing: 20200702VNU
      org.nokogiri:nekodtd: 0.1.11.noko2
      xalan:serializer: 2.7.3
      xalan:xalan: 2.7.3
      xerces:xercesImpl: 2.12.2
      xml-apis:xml-apis: 1.4.01

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions