class Nokogiri::XML::Node - nokogiri-1.15.2 Documentation

# class Nokogiri::XML::Node

`Nokogiri::XML::Node` is the primary API you’ll use to interact with your `Document`.

## Attributes¶ ↑

A `Nokogiri::XML::Node` may be treated similarly to a hash with regard to attributes. For example:

    node = Nokogiri::XML::DocumentFragment.parse("<a href='#foo' id='link'>link</a>").at_css("a")
    node.to_html # => "<a href=\"#foo\" id=\"link\">link</a>"
    node['href'] # => "#foo"
    node.keys # => ["href", "id"]
    node.values # => ["#foo", "link"]
    node['class'] = 'green' # => "green"
    node.to_html # => "<a href=\"#foo\" id=\"link\" class=\"green\">link</a>"

See the method group entitled Working With Node Attributes at `Node` for the full set of methods.

## Navigation¶ ↑

`Nokogiri::XML::Node` also has methods that let you move around your tree:

`parent`, `children`, `next`, `previous`

  Navigate up, down, or through siblings.

See the method group entitled Traversing Document Structure at `Node` for the full set of methods.

## Serialization¶ ↑

When printing or otherwise emitting a document or a node (and its subtree), there are a few methods you might want to use:

`content`, `text`, `inner_text`, `to_str`

  These methods will all **emit plaintext**, meaning that entities will be replaced (e.g., +&lt;+ will be replaced with +<+), meaning that any sanitizing will likely be un-done in the output.

`to_s`, `to_xml`, `to_html`, `inner_html`

  These methods will all **emit properly-escaped markup**, meaning that it’s suitable for consumption by browsers, parsers, etc.

See the method group entitled Serialization and Generating Output at `Node` for the full set of methods.

## Searching¶ ↑

You may search this node’s subtree using methods like `xpath` and `css`.

See the method group entitled Searching via XPath or CSS Queries at `Node` for the full set of methods.

### Constants

ATTRIBUTE_DECL

  Attribute declaration type

ATTRIBUTE_NODE

  Attribute node type

CDATA_SECTION_NODE

  `CDATA` node type, see `Nokogiri::XML::Node#cdata?`

COMMENT_NODE

  `Comment` node type, see `Nokogiri::XML::Node#comment?`

DOCB_DOCUMENT_NODE

  DOCB document node type

DOCUMENT_FRAG_NODE

  `Document` fragment node type

DOCUMENT_NODE

  `Document` node type, see `Nokogiri::XML::Node#xml?`

DOCUMENT_TYPE_NODE

  `Document` type node type

DTD_NODE

  `DTD` node type

ELEMENT_DECL

  `Element` declaration type

ELEMENT_NODE

  `Element` node type, see `Nokogiri::XML::Node#element?`

ENTITY_DECL

  Entity declaration type

ENTITY_NODE

  Entity node type

ENTITY_REF_NODE

  Entity reference node type

HTML_DOCUMENT_NODE

  `HTML` document node type, see `Nokogiri::XML::Node#html?`

IMPLIED_XPATH_CONTEXTS
NAMESPACE_DECL

  `Namespace` declaration type

NOTATION_NODE

  `Notation` node type

PI_NODE

  PI node type

TEXT_NODE

  `Text` node type, see `Nokogiri::XML::Node#text?`

USING_LIBXML_WITH_BROKEN_SERIALIZATION
XINCLUDE_END

  XInclude end type

XINCLUDE_START

  XInclude start type

### Public Class Methods

new(name, document) → Nokogiri::XML::Node click to toggle source
new(name, document) { |node| ... } → Nokogiri::XML::Node

Create a new node with `name` that belongs to `document`.

If you intend to add a node to a document tree, it’s likely that you will prefer one of the `Nokogiri::XML::Node` methods like `add_child`, `add_next_sibling`, `replace`, etc. which will both create an element (or subtree) and place it in the document tree.

Another alternative, if you are concerned about performance, is Nokogiri::XML::Document#create_element which accepts additional arguments for contents or attributes but (like this method) avoids parsing markup.

Parameters

- `name` (String)

- `document` (`Nokogiri::XML::Document`) The document to which the the returned node will belong.

Yields

  `Nokogiri::XML::Node`

Returns

  `Nokogiri::XML::Node`

    # File lib/nokogiri/xml/node.rb, line 126
    def initialize(name, document)
      # This is intentionally empty, and sets the method signature for subclasses.
    end

### Public Instance Methods

<=>(other) click to toggle source

Compare two `Node` objects with respect to their `Document`. Nodes from different documents cannot be compared.

    # File lib/nokogiri/xml/node.rb, line 1256
    def <=>(other)
      return nil unless other.is_a?(Nokogiri::XML::Node)
      return nil unless document == other.document

      compare(other)
    end

==(other) click to toggle source

`Test` to see if this `Node` is equal to `other`

    # File lib/nokogiri/xml/node.rb, line 1246
    def ==(other)
      return false unless other
      return false unless other.respond_to?(:pointer_id)

      pointer_id == other.pointer_id
    end

accept(visitor) click to toggle source

Accept a visitor. This method calls “visit” on `visitor` with self.

    # File lib/nokogiri/xml/node.rb, line 1240
    def accept(visitor)
      visitor.visit(self)
    end

ancestors(selector = nil) click to toggle source

Get a list of ancestor `Node` for this `Node`. If `selector` is given, the ancestors must match `selector`

    # File lib/nokogiri/xml/node.rb, line 1209
    def ancestors(selector = nil)
      return NodeSet.new(document) unless respond_to?(:parent)
      return NodeSet.new(document) unless parent

      parents = [parent]

      while parents.last.respond_to?(:parent)
        break unless (ctx_parent = parents.last.parent)

        parents << ctx_parent
      end

      return NodeSet.new(document, parents) unless selector

      root = parents.last
      search_results = root.search(selector)

      NodeSet.new(document, parents.find_all do |parent|
        search_results.include?(parent)
      end)
    end

blank? → Boolean click to toggle source

Returns

  `true` if the node is an empty or whitespace-only text or cdata node, else `false`.

Example:

    Nokogiri("<root><child/></root>").root.child.blank? # => false
    Nokogiri("<root>\t \n</root>").root.child.blank? # => true
    Nokogiri("<root><![CDATA[\t \n]]></root>").root.child.blank? # => true
    Nokogiri("<root>not-blank</root>").root.child
      .tap { |n| n.content = "" }.blank # => true

    static VALUE
    rb_xml_node_blank_eh(VALUE self)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
    }

cdata?() click to toggle source

Returns true if this is a `CDATA`

    # File lib/nokogiri/xml/node.rb, line 1130
    def cdata?
      type == CDATA_SECTION_NODE
    end

clone(p1 = v1, p2 = v2)
Alias for: dup
comment?() click to toggle source

Returns true if this is a `Comment`

    # File lib/nokogiri/xml/node.rb, line 1125
    def comment?
      type == COMMENT_NODE
    end

content() → String click to toggle source

Returns

  Contents of all the text nodes in this node’s subtree, concatenated together into a single String.

⚠ Note that entities will always be expanded in the returned String.

See related: `inner_html`

Example of how entities are handled:

Note that `&lt;` becomes `<` in the returned String.

    doc = Nokogiri::XML.fragment("<child>a &lt; b</child>")
    doc.at_css("child").content
    # => "a < b"

Example of how a subtree is handled:

Note that the `<span>` tags are omitted and only the text node contents are returned, concatenated into a single string.

    doc = Nokogiri::XML.fragment("<child><span>first</span> <span>second</span></child>")
    doc.at_css("child").content
    # => "first second"

    static VALUE
    rb_xml_node_content(VALUE self)
    {
      xmlNodePtr node;
      xmlChar *content;

      Noko_Node_Get_Struct(self, xmlNode, node);

      content = xmlNodeGetContent(node);
      if (content) {
        VALUE rval = NOKOGIRI_STR_NEW2(content);
        xmlFree(content);
        return rval;
      }
      return Qnil;
    }

Also aliased as: inner_text, text, to_str
create_external_subset(name, external_id, system_id) click to toggle source

Create an external subset

    static VALUE
    create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
    {
      xmlNodePtr node;
      xmlDocPtr doc;
      xmlDtdPtr dtd;

      Noko_Node_Get_Struct(self, xmlNode, node);

      doc = node->doc;

      if (doc->extSubset) {
        rb_raise(rb_eRuntimeError, "Document already has an external subset");
      }

      dtd = xmlNewDtd(
              doc,
              NIL_P(name)        ? NULL : (const xmlChar *)StringValueCStr(name),
              NIL_P(external_id) ? NULL : (const xmlChar *)StringValueCStr(external_id),
              NIL_P(system_id)   ? NULL : (const xmlChar *)StringValueCStr(system_id)
            );

      if (!dtd) { return Qnil; }

      return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
    }

create_internal_subset(name, external_id, system_id) click to toggle source

Create the internal subset of a document.

    doc.create_internal_subset("chapter", "-//OASIS//DTD DocBook XML//EN", "chapter.dtd")
    # => <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML//EN" "chapter.dtd">

    doc.create_internal_subset("chapter", nil, "chapter.dtd")
    # => <!DOCTYPE chapter SYSTEM "chapter.dtd">

    static VALUE
    create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
    {
      xmlNodePtr node;
      xmlDocPtr doc;
      xmlDtdPtr dtd;

      Noko_Node_Get_Struct(self, xmlNode, node);

      doc = node->doc;

      if (xmlGetIntSubset(doc)) {
        rb_raise(rb_eRuntimeError, "Document already has an internal subset");
      }

      dtd = xmlCreateIntSubset(
              doc,
              NIL_P(name)        ? NULL : (const xmlChar *)StringValueCStr(name),
              NIL_P(external_id) ? NULL : (const xmlChar *)StringValueCStr(external_id),
              NIL_P(system_id)   ? NULL : (const xmlChar *)StringValueCStr(system_id)
            );

      if (!dtd) { return Qnil; }

      return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
    }

css_path() click to toggle source

Get the path to this node as a `CSS` expression

    # File lib/nokogiri/xml/node.rb, line 1200
    def css_path
      path.split(%r{/}).filter_map do |part|
        part.empty? ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)')
      end.join(" > ")
    end

decorate!() click to toggle source

Decorate this node with the decorators set up in this node’s `Document`

    # File lib/nokogiri/xml/node.rb, line 132
    def decorate!
      document.decorate(self)
    end

description() click to toggle source

Fetch the `Nokogiri::HTML4::ElementDescription` for this node. Returns nil on `XML` documents and on unknown tags.

    # File lib/nokogiri/xml/node.rb, line 1167
    def description
      return nil if document.xml?

      Nokogiri::HTML4::ElementDescription[name]
    end

document?() click to toggle source

Returns true if this is a `Document`

    # File lib/nokogiri/xml/node.rb, line 1145
    def document?
      is_a?(XML::Document)
    end

dup → Nokogiri::XML::Node click to toggle source
dup(depth) → Nokogiri::XML::Node
dup(depth, new_parent_doc) → Nokogiri::XML::Node

Copy this node.

Parameters

- `depth` 0 is a shallow copy, 1 (the default) is a deep copy.

- `new_parent_doc` The new node’s parent `Document`. Defaults to the this node’s document.

Returns

  The new Nokgiri::XML::Node

    static VALUE
    duplicate_node(int argc, VALUE *argv, VALUE self)
    {
      VALUE r_level, r_new_parent_doc;
      int level;
      int n_args;
      xmlDocPtr new_parent_doc;
      xmlNodePtr node, dup;

      Noko_Node_Get_Struct(self, xmlNode, node);

      n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);

      if (n_args < 1) {
        r_level = INT2NUM((long)1);
      }
      level = (int)NUM2INT(r_level);

      if (n_args < 2) {
        new_parent_doc = node->doc;
      } else {
        new_parent_doc = noko_xml_document_unwrap(r_new_parent_doc);
      }

      dup = xmlDocCopyNode(node, new_parent_doc, level);
      if (dup == NULL) { return Qnil; }

      noko_xml_document_pin_node(dup);

      return noko_xml_node_wrap(rb_obj_class(self), dup);
    }

Also aliased as: clone
elem?()
Alias for: element?
element?() click to toggle source

Returns true if this is an `Element` node

    # File lib/nokogiri/xml/node.rb, line 1181
    def element?
      type == ELEMENT_NODE
    end

Also aliased as: elem?
element_children() → NodeSet click to toggle source

Returns

  The node’s child elements as a `NodeSet`. Only children that are elements will be returned, which notably excludes `Text` nodes.

Example:

Note that `children` returns the `Text` node “hello” while `element_children` does not.

    div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
    div.element_children
    # => [#<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
    div.children
    # => [#<Nokogiri::XML::Text:0x64 "hello">,
    #     #<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]

    static VALUE
    rb_xml_node_element_children(VALUE self)
    {
      xmlNodePtr node;
      xmlNodePtr child;
      xmlNodeSetPtr set;
      VALUE document;
      VALUE node_set;

      Noko_Node_Get_Struct(self, xmlNode, node);

      child = xmlFirstElementChild(node);
      set = xmlXPathNodeSetCreate(child);

      document = DOC_RUBY_OBJECT(node->doc);

      if (!child) { return noko_xml_node_set_wrap(set, document); }

      child = xmlNextElementSibling(child);
      while (NULL != child) {
        xmlXPathNodeSetAddUnique(set, child);
        child = xmlNextElementSibling(child);
      }

      node_set = noko_xml_node_set_wrap(set, document);

      return node_set;
    }

Also aliased as: elements
elements() → NodeSet
Alias for: element_children
encode_special_chars(string) → String click to toggle source

Encode any special characters in `string`

    static VALUE
    encode_special_chars(VALUE self, VALUE string)
    {
      xmlNodePtr node;
      xmlChar *encoded;
      VALUE encoded_str;

      Noko_Node_Get_Struct(self, xmlNode, node);
      encoded = xmlEncodeSpecialChars(
                  node->doc,
                  (const xmlChar *)StringValueCStr(string)
                );

      encoded_str = NOKOGIRI_STR_NEW2(encoded);
      xmlFree(encoded);

      return encoded_str;
    }

external_subset() click to toggle source

Get the external subset

    static VALUE
    external_subset(VALUE self)
    {
      xmlNodePtr node;
      xmlDocPtr doc;
      xmlDtdPtr dtd;

      Noko_Node_Get_Struct(self, xmlNode, node);

      if (!node->doc) { return Qnil; }

      doc = node->doc;
      dtd = doc->extSubset;

      if (!dtd) { return Qnil; }

      return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
    }

first_element_child() → Node click to toggle source

Returns

  The first child `Node` that is an element.

Example:

Note that the “hello” child, which is a `Text` node, is skipped and the `<span>` element is returned.

    div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
    div.first_element_child
    # => #(Element:0x3c { name = "span", children = [ #(Text "world")] })

    static VALUE
    rb_xml_node_first_element_child(VALUE self)
    {
      xmlNodePtr node, child;
      Noko_Node_Get_Struct(self, xmlNode, node);

      child = xmlFirstElementChild(node);
      if (!child) { return Qnil; }

      return noko_xml_node_wrap(Qnil, child);
    }

fragment(tags) click to toggle source

Create a `DocumentFragment` containing `tags` that is relative to this context node.

    # File lib/nokogiri/xml/node.rb, line 1022
    def fragment(tags)
      document.related_class("DocumentFragment").new(document, tags, self)
    end

fragment?() click to toggle source

Returns true if this is a `DocumentFragment`

    # File lib/nokogiri/xml/node.rb, line 1160
    def fragment?
      type == DOCUMENT_FRAG_NODE
    end

html?() click to toggle source

Returns true if this is an `HTML4::Document` or `HTML5::Document` node

    # File lib/nokogiri/xml/node.rb, line 1140
    def html?
      type == HTML_DOCUMENT_NODE
    end

inner_html(*args) click to toggle source

Get the `inner_html` for this node’s `Node#children`

    # File lib/nokogiri/xml/node.rb, line 1195
    def inner_html(*args)
      children.map { |x| x.to_html(*args) }.join
    end

inner_text()
Alias for: content
internal_subset() click to toggle source

Get the internal subset

    static VALUE
    internal_subset(VALUE self)
    {
      xmlNodePtr node;
      xmlDocPtr doc;
      xmlDtdPtr dtd;

      Noko_Node_Get_Struct(self, xmlNode, node);

      if (!node->doc) { return Qnil; }

      doc = node->doc;
      dtd = xmlGetIntSubset(doc);

      if (!dtd) { return Qnil; }

      return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
    }

key?(attribute) click to toggle source

Returns true if `attribute` is set

    static VALUE
    key_eh(VALUE self, VALUE attribute)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
        return Qtrue;
      }
      return Qfalse;
    }

Also aliased as: has_attribute?
lang click to toggle source

Searches the language of a node, i.e. the values of the xml:lang attribute or the one carried by the nearest ancestor.

    static VALUE
    get_lang(VALUE self_rb)
    {
      xmlNodePtr self ;
      xmlChar *lang ;
      VALUE lang_rb ;

      Noko_Node_Get_Struct(self_rb, xmlNode, self);

      lang = xmlNodeGetLang(self);
      if (lang) {
        lang_rb = NOKOGIRI_STR_NEW2(lang);
        xmlFree(lang);
        return lang_rb ;
      }

      return Qnil ;
    }

lang= click to toggle source

Set the language of a node, i.e. the values of the xml:lang attribute.

    static VALUE
    set_lang(VALUE self_rb, VALUE lang_rb)
    {
      xmlNodePtr self ;
      xmlChar *lang ;

      Noko_Node_Get_Struct(self_rb, xmlNode, self);
      lang = (xmlChar *)StringValueCStr(lang_rb);

      xmlNodeSetLang(self, lang);

      return Qnil ;
    }

last_element_child() → Node click to toggle source

Returns

  The last child `Node` that is an element.

Example:

Note that the “hello” child, which is a `Text` node, is skipped and the `<span>yes</span>` element is returned.

    div = Nokogiri::HTML5("<div><span>no</span><span>yes</span>skip</div>").at_css("div")
    div.last_element_child
    # => #(Element:0x3c { name = "span", children = [ #(Text "yes")] })

    static VALUE
    rb_xml_node_last_element_child(VALUE self)
    {
      xmlNodePtr node, child;
      Noko_Node_Get_Struct(self, xmlNode, node);

      child = xmlLastElementChild(node);
      if (!child) { return Qnil; }

      return noko_xml_node_wrap(Qnil, child);
    }

line() → Integer click to toggle source

Returns

  The line number of this `Node`.

⚠ The CRuby and JRuby implementations differ in important ways!

Semantic differences:

- The CRuby method reflects the node’s line number in the parsed string

- The JRuby method reflects the node’s line number in the final DOM structure after corrections have been applied

Performance differences:

- The CRuby method is O(1) (constant time)

- The JRuby method is O(n) (linear time, where n is the number of nodes before/above the element in the DOM)

If you’d like to help improve the JRuby implementation, please review these issues and reach out to the maintainers:

- github.com/sparklemotion/nokogiri/issues/1223

- github.com/sparklemotion/nokogiri/pull/2177

- github.com/sparklemotion/nokogiri/issues/2380

    static VALUE
    rb_xml_node_line(VALUE rb_node)
    {
      xmlNodePtr c_node;
      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

      return LONG2NUM(xmlGetLineNo(c_node));
    }

line=(num) click to toggle source

Sets the line for this `Node`. num must be less than 65535.

    static VALUE
    rb_xml_node_line_set(VALUE rb_node, VALUE rb_line_number)
    {
      xmlNodePtr c_node;
      int line_number = NUM2INT(rb_line_number);

      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

      // libxml2 optionally uses xmlNode.psvi to store longer line numbers, but only for text nodes.
      // search for "psvi" in SAX2.c and tree.c to learn more.
      if (line_number < 65535) {
        c_node->line = (short) line_number;
      } else {
        c_node->line = 65535;
        if (c_node->type == XML_TEXT_NODE) {
          c_node->psvi = (void *)(ptrdiff_t) line_number;
        }
      }

      return rb_line_number;
    }

matches?(selector) click to toggle source

Returns true if this `Node` matches `selector`

    # File lib/nokogiri/xml/node.rb, line 1015
    def matches?(selector)
      ancestors.last.search(selector).include?(self)
    end

name
Alias for: node_name
namespace() → Namespace click to toggle source

Returns

  The `Namespace` of the element or attribute node, or `nil` if there is no namespace.

Example:

    doc = Nokogiri::XML(<<~EOF)
      <root>
        <first/>
        <second xmlns="http://example.com/child"/>
        <foo:third xmlns:foo="http://example.com/foo"/>
      </root>
    EOF
    doc.at_xpath("//first").namespace
    # => nil
    doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace
    # => #(Namespace:0x3c { href = "http://example.com/child" })
    doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace
    # => #(Namespace:0x50 { prefix = "foo", href = "http://example.com/foo" })

    static VALUE
    rb_xml_node_namespace(VALUE rb_node)
    {
      xmlNodePtr c_node ;
      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

      if (c_node->ns) {
        return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
      }

      return Qnil ;
    }

namespace_definitions() → Array<Nokogiri::XML::Namespace> click to toggle source

Returns

  Namespaces that are defined directly on this node, as an Array of `Namespace` objects. The array will be empty if no namespaces are defined on this node.

Example:

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns="http://example.com/root">
        <first/>
        <second xmlns="http://example.com/child" xmlns:unused="http://example.com/unused"/>
        <foo:third xmlns:foo="http://example.com/foo"/>
      </root>
    EOF
    doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_definitions
    # => []
    doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace_definitions
    # => [#(Namespace:0x3c { href = "http://example.com/child" }),
    #     #(Namespace:0x50 {
    #       prefix = "unused",
    #       href = "http://example.com/unused"
    #       })]
    doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace_definitions
    # => [#(Namespace:0x64 { prefix = "foo", href = "http://example.com/foo" })]

    static VALUE
    namespace_definitions(VALUE rb_node)
    {
      /* this code in the mode of xmlHasProp() */
      xmlNodePtr c_node ;
      xmlNsPtr c_namespace;
      VALUE definitions = rb_ary_new();

      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

      c_namespace = c_node->nsDef;
      if (!c_namespace) {
        return definitions;
      }

      while (c_namespace != NULL) {
        rb_ary_push(definitions, noko_xml_namespace_wrap(c_namespace, c_node->doc));
        c_namespace = c_namespace->next;
      }

      return definitions;
    }

namespace_scopes() → Array<Nokogiri::XML::Namespace> click to toggle source

Returns

  Array of all the Namespaces on this node and its ancestors.

See also `namespaces`

Example:

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns="http://example.com/root" xmlns:bar="http://example.com/bar">
        <first/>
        <second xmlns="http://example.com/child"/>
        <third xmlns:foo="http://example.com/foo"/>
      </root>
    EOF
    doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_scopes
    # => [#(Namespace:0x3c { href = "http://example.com/root" }),
    #     #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
    doc.at_xpath("//child:second", "child" => "http://example.com/child").namespace_scopes
    # => [#(Namespace:0x64 { href = "http://example.com/child" }),
    #     #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
    doc.at_xpath("//root:third", "root" => "http://example.com/root").namespace_scopes
    # => [#(Namespace:0x78 { prefix = "foo", href = "http://example.com/foo" }),
    #     #(Namespace:0x3c { href = "http://example.com/root" }),
    #     #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]

    static VALUE
    rb_xml_node_namespace_scopes(VALUE rb_node)
    {
      xmlNodePtr c_node ;
      xmlNsPtr *namespaces;
      VALUE scopes = rb_ary_new();
      int j;

      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

      namespaces = xmlGetNsList(c_node->doc, c_node);
      if (!namespaces) {
        return scopes;
      }

      for (j = 0 ; namespaces[j] != NULL ; ++j) {
        rb_ary_push(scopes, noko_xml_namespace_wrap(namespaces[j], c_node->doc));
      }

      xmlFree(namespaces);
      return scopes;
    }

namespaced_key?(attribute, namespace) click to toggle source

Returns true if `attribute` is set with `namespace`

    static VALUE
    namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
                       NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
        return Qtrue;
      }
      return Qfalse;
    }

namespaces() → Hash<String(Namespace#prefix) ⇒ String(Namespace#href)> click to toggle source

Fetch all the namespaces on this node and its ancestors.

Note that the keys in this hash `XML` attributes that would be used to define this namespace, such as “xmlns:prefix”, not just the prefix.

The default namespace for this node will be included with key “xmlns”.

See also `namespace_scopes`

Returns

  Hash containing all the namespaces on this node and its ancestors. The hash keys are the namespace prefix, and the hash value for each key is the namespace URI.

Example:

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns="http://example.com/root" xmlns:in_scope="http://example.com/in_scope">
        <first/>
        <second xmlns="http://example.com/child"/>
        <third xmlns:foo="http://example.com/foo"/>
      </root>
    EOF
    doc.at_xpath("//root:first", "root" => "http://example.com/root").namespaces
    # => {"xmlns"=>"http://example.com/root",
    #     "xmlns:in_scope"=>"http://example.com/in_scope"}
    doc.at_xpath("//child:second", "child" => "http://example.com/child").namespaces
    # => {"xmlns"=>"http://example.com/child",
    #     "xmlns:in_scope"=>"http://example.com/in_scope"}
    doc.at_xpath("//root:third", "root" => "http://example.com/root").namespaces
    # => {"xmlns:foo"=>"http://example.com/foo",
    #     "xmlns"=>"http://example.com/root",
    #     "xmlns:in_scope"=>"http://example.com/in_scope"}

    # File lib/nokogiri/xml/node.rb, line 1116
    def namespaces
      namespace_scopes.each_with_object({}) do |ns, hash|
        prefix = ns.prefix
        key = prefix ? "xmlns:#{prefix}" : "xmlns"
        hash[key] = ns.href
      end
    end

content= click to toggle source

Set the content for this `Node`

    static VALUE
    set_native_content(VALUE self, VALUE content)
    {
      xmlNodePtr node, child, next ;
      Noko_Node_Get_Struct(self, xmlNode, node);

      child = node->children;
      while (NULL != child) {
        next = child->next ;
        xmlUnlinkNode(child) ;
        noko_xml_document_pin_node(child);
        child = next ;
      }

      xmlNodeSetContent(node, (xmlChar *)StringValueCStr(content));
      return content;
    }

next_element click to toggle source

Returns the next `Nokogiri::XML::Element` type sibling node.

    static VALUE
    next_element(VALUE self)
    {
      xmlNodePtr node, sibling;
      Noko_Node_Get_Struct(self, xmlNode, node);

      sibling = xmlNextElementSibling(node);
      if (!sibling) { return Qnil; }

      return noko_xml_node_wrap(Qnil, sibling);
    }

next_sibling click to toggle source

Returns the next sibling node

    static VALUE
    next_sibling(VALUE self)
    {
      xmlNodePtr node, sibling;
      Noko_Node_Get_Struct(self, xmlNode, node);

      sibling = node->next;
      if (!sibling) { return Qnil; }

      return noko_xml_node_wrap(Qnil, sibling) ;
    }

Also aliased as: next
name click to toggle source

Returns the name for this `Node`

    static VALUE
    get_name(VALUE self)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      if (node->name) {
        return NOKOGIRI_STR_NEW2(node->name);
      }
      return Qnil;
    }

Also aliased as: name
node_name=(new_name) click to toggle source

Set the name for this `Node`

    static VALUE
    set_name(VALUE self, VALUE new_name)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
      return new_name;
    }

Also aliased as: name=
node_type click to toggle source

Get the type for this `Node`

    static VALUE
    node_type(VALUE self)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      return INT2NUM(node->type);
    }

Also aliased as: type
parent click to toggle source

Get the parent `Node` for this `Node`

    static VALUE
    get_parent(VALUE self)
    {
      xmlNodePtr node, parent;
      Noko_Node_Get_Struct(self, xmlNode, node);

      parent = node->parent;
      if (!parent) { return Qnil; }

      return noko_xml_node_wrap(Qnil, parent) ;
    }

parse(string_or_io, options = nil) { |options| ... } click to toggle source

Parse `string_or_io` as a document fragment within the context of this node. Returns a `XML::NodeSet` containing the nodes parsed from `string_or_io`.

    # File lib/nokogiri/xml/node.rb, line 1030
    def parse(string_or_io, options = nil)
      ##
      # When the current node is unparented and not an element node, use the
      # document as the parsing context instead. Otherwise, the in-context
      # parser cannot find an element or a document node.
      # Document Fragments are also not usable by the in-context parser.
      if !element? && !document? && (!parent || parent.fragment?)
        return document.parse(string_or_io, options)
      end

      options ||= (document.html? ? ParseOptions::DEFAULT_HTML : ParseOptions::DEFAULT_XML)
      options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
      yield options if block_given?

      contents = if string_or_io.respond_to?(:read)
        string_or_io.read
      else
        string_or_io
      end

      return Nokogiri::XML::NodeSet.new(document) if contents.empty?

      # libxml2 does not obey the +recover+ option after encountering errors during +in_context+
      # parsing, and so this horrible hack is here to try to emulate recovery behavior.
      #
      # Unfortunately, this means we're no longer parsing "in context" and so namespaces that
      # would have been inherited from the context node won't be handled correctly. This hack was
      # written in 2010, and I regret it, because it's silently degrading functionality in a way
      # that's not easily prevented (or even detected).
      #
      # I think preferable behavior would be to either:
      #
      # a. add an error noting that we "fell back" and pointing the user to turning off the +recover+ option
      # b. don't recover, but raise a sensible exception
      #
      # For context and background: https://github.com/sparklemotion/nokogiri/issues/313
      # FIXME bug report: https://github.com/sparklemotion/nokogiri/issues/2092
      error_count = document.errors.length
      node_set = in_context(contents, options.to_i)
      if node_set.empty? && (document.errors.length > error_count)
        if options.recover?
          fragment = document.related_class("DocumentFragment").parse(contents)
          node_set = fragment.children
        else
          raise document.errors[error_count]
        end
      end
      node_set
    end

path click to toggle source

Returns the path associated with this `Node`

    static VALUE
    rb_xml_node_path(VALUE rb_node)
    {
      xmlNodePtr c_node;
      xmlChar *c_path ;
      VALUE rval;

      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

      c_path = xmlGetNodePath(c_node);
      if (c_path == NULL) {
        // see https://github.com/sparklemotion/nokogiri/issues/2250
        // this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
        // do this for now to preserve the behavior across libxml2 versions.
        rval = NOKOGIRI_STR_NEW2("?");
      } else {
        rval = NOKOGIRI_STR_NEW2(c_path);
        xmlFree(c_path);
      }

      return rval ;
    }

pointer_id() → Integer click to toggle source

Returns

  A unique id for this node based on the internal memory structures. This method is used by `==` to determine node identity.

    static VALUE
    rb_xml_node_pointer_id(VALUE self)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);

      return rb_uint2inum((uintptr_t)(node));
    }

previous_element click to toggle source

Returns the previous `Nokogiri::XML::Element` type sibling node.

    static VALUE
    previous_element(VALUE self)
    {
      xmlNodePtr node, sibling;
      Noko_Node_Get_Struct(self, xmlNode, node);

      /*
       *  note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
       */
      sibling = node->prev;
      if (!sibling) { return Qnil; }

      while (sibling && sibling->type != XML_ELEMENT_NODE) {
        sibling = sibling->prev;
      }

      return sibling ? noko_xml_node_wrap(Qnil, sibling) : Qnil ;
    }

previous_sibling click to toggle source

Returns the previous sibling node

    static VALUE
    previous_sibling(VALUE self)
    {
      xmlNodePtr node, sibling;
      Noko_Node_Get_Struct(self, xmlNode, node);

      sibling = node->prev;
      if (!sibling) { return Qnil; }

      return noko_xml_node_wrap(Qnil, sibling);
    }

Also aliased as: previous
processing_instruction?() click to toggle source

Returns true if this is a `ProcessingInstruction` node

    # File lib/nokogiri/xml/node.rb, line 1150
    def processing_instruction?
      type == PI_NODE
    end

read_only?() click to toggle source

Is this a read only node?

    # File lib/nokogiri/xml/node.rb, line 1175
    def read_only?
      # According to gdome2, these are read-only node types
      [NOTATION_NODE, ENTITY_NODE, ENTITY_DECL].include?(type)
    end

text() → String
Alias for: content
text?() click to toggle source

Returns true if this is a `Text` node

    # File lib/nokogiri/xml/node.rb, line 1155
    def text?
      type == TEXT_NODE
    end

to_s() click to toggle source

Turn this node in to a string. If the document is `HTML`, this method returns html. If the document is `XML`, this method returns `XML`.

    # File lib/nokogiri/xml/node.rb, line 1190
    def to_s
      document.xml? ? to_xml : to_html
    end

to_str() → String
Alias for: content
traverse() { |self| ... } click to toggle source

Yields self and all children to `block` recursively.

    # File lib/nokogiri/xml/node.rb, line 1233
    def traverse(&block)
      children.each { |j| j.traverse(&block) }
      yield(self)
    end

node_type
Alias for: node_type
unlink() → self click to toggle source

Unlink this node from its current context.

    static VALUE
    unlink_node(VALUE self)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      xmlUnlinkNode(node);
      noko_xml_document_pin_node(node);
      return self;
    }

Also aliased as: remove
xml?() click to toggle source

Returns true if this is an `XML::Document` node

    # File lib/nokogiri/xml/node.rb, line 1135
    def xml?
      type == DOCUMENT_NODE
    end

### Protected Instance Methods

coerce(data) click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1482
          def coerce(data)
            case data
            when XML::NodeSet
              return data
            when XML::DocumentFragment
              return data.children
            when String
              return fragment(data).children
            when Document, XML::Attr
              # unacceptable
            when XML::Node
              return data
            end

            raise ArgumentError, <<~EOERR
              Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
              (You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
            EOERR
          end

### Private Instance Methods

add_child_node_and_reparent_attrs(node) click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1561
    def add_child_node_and_reparent_attrs(node)
      add_child_node(node)
      node.attribute_nodes.find_all { |a| a.name.include?(":") }.each do |attr_node|
        attr_node.remove
        node[attr_node.name] = attr_node.value
      end
    end

add_sibling(next_or_previous, node_or_tags) click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1516
    def add_sibling(next_or_previous, node_or_tags)
      raise("Cannot add sibling to a node with no parent") unless parent

      impl = next_or_previous == :next ? :add_next_sibling_node : :add_previous_sibling_node
      iter = next_or_previous == :next ? :reverse_each : :each

      node_or_tags = parent.coerce(node_or_tags)
      if node_or_tags.is_a?(XML::NodeSet)
        if text?
          pivot = Nokogiri::XML::Node.new("dummy", document)
          send(impl, pivot)
        else
          pivot = self
        end
        node_or_tags.send(iter) { |n| pivot.send(impl, n) }
        pivot.unlink if text?
      else
        send(impl, node_or_tags)
      end
      node_or_tags
    end

compare(other) click to toggle source

Compare this `Node` to `other` with respect to their `Document`

    static VALUE
    compare(VALUE self, VALUE _other)
    {
      xmlNodePtr node, other;
      Noko_Node_Get_Struct(self, xmlNode, node);
      Noko_Node_Get_Struct(_other, xmlNode, other);

      return INT2NUM(xmlXPathCmpNodes(other, node));
    }

dump_html click to toggle source

Returns the `Node` as html.

    static VALUE
    dump_html(VALUE self)
    {
      xmlBufferPtr buf ;
      xmlNodePtr node ;
      VALUE html;

      Noko_Node_Get_Struct(self, xmlNode, node);

      buf = xmlBufferCreate() ;
      htmlNodeDump(buf, node->doc, node);
      html = NOKOGIRI_STR_NEW2(buf->content);
      xmlBufferFree(buf);
      return html ;
    }

get(attribute) click to toggle source

Get the value for `attribute`

    static VALUE
    get(VALUE self, VALUE rattribute)
    {
      xmlNodePtr node;
      xmlChar *value = 0;
      VALUE rvalue;
      xmlChar *colon;
      xmlChar *attribute, *attr_name, *prefix;
      xmlNsPtr ns;

      if (NIL_P(rattribute)) { return Qnil; }

      Noko_Node_Get_Struct(self, xmlNode, node);
      attribute = xmlCharStrdup(StringValueCStr(rattribute));

      colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
      if (colon) {
        /* split the attribute string into separate prefix and name by
         * null-terminating the prefix at the colon */
        prefix = attribute;
        attr_name = colon + 1;
        (*colon) = 0;

        ns = xmlSearchNs(node->doc, node, prefix);
        if (ns) {
          value = xmlGetNsProp(node, attr_name, ns->href);
        } else {
          value = xmlGetProp(node, (xmlChar *)StringValueCStr(rattribute));
        }
      } else {
        value = xmlGetNoNsProp(node, attribute);
      }

      xmlFree((void *)attribute);
      if (!value) { return Qnil; }

      rvalue = NOKOGIRI_STR_NEW2(value);
      xmlFree((void *)value);

      return rvalue ;
    }

html_standard_serialize(p1) click to toggle source

    static VALUE
    html_standard_serialize(
      VALUE self,
      VALUE preserve_newline
    )
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      VALUE output = rb_str_buf_new(4096);
      output_node(output, node, RTEST(preserve_newline));
      return output;
    }

in_context(p1, p2) click to toggle source

TODO: DOCUMENT ME

    static VALUE
    in_context(VALUE self, VALUE _str, VALUE _options)
    {
      xmlNodePtr node, list = 0, tmp, child_iter, node_children, doc_children;
      xmlNodeSetPtr set;
      xmlParserErrors error;
      VALUE doc, err;
      int doc_is_empty;

      Noko_Node_Get_Struct(self, xmlNode, node);

      doc = DOC_RUBY_OBJECT(node->doc);
      err = rb_iv_get(doc, "@errors");
      doc_is_empty = (node->doc->children == NULL) ? 1 : 0;
      node_children = node->children;
      doc_children  = node->doc->children;

      xmlSetStructuredErrorFunc((void *)err, Nokogiri_error_array_pusher);

      /* Twiddle global variable because of a bug in libxml2.
       * http://git.gnome.org/browse/libxml2/commit/?id=e20fb5a72c83cbfc8e4a8aa3943c6be8febadab7
       */
    #ifndef HTML_PARSE_NOIMPLIED
      htmlHandleOmittedElem(0);
    #endif

      /* This function adds a fake node to the child of +node+.  If the parser
       * does not exit cleanly with XML_ERR_OK, the list is freed.  This can
       * leave the child pointers in a bad state if they were originally empty.
       *
       * http://git.gnome.org/browse/libxml2/tree/parser.c#n13177
       * */
      error = xmlParseInNodeContext(node, StringValuePtr(_str),
                                    (int)RSTRING_LEN(_str),
                                    (int)NUM2INT(_options), &list);

      /* xmlParseInNodeContext should not mutate the original document or node,
       * so reassigning these pointers should be OK.  The reason we're reassigning
       * is because if there were errors, it's possible for the child pointers
       * to be manipulated. */
      if (error != XML_ERR_OK) {
        node->doc->children = doc_children;
        node->children = node_children;
      }

      /* make sure parent/child pointers are coherent so an unlink will work
       * properly (#331)
       */
      child_iter = node->doc->children ;
      while (child_iter) {
        child_iter->parent = (xmlNodePtr)node->doc;
        child_iter = child_iter->next;
      }

    #ifndef HTML_PARSE_NOIMPLIED
      htmlHandleOmittedElem(1);
    #endif

      xmlSetStructuredErrorFunc(NULL, NULL);

      /*
       * Workaround for a libxml2 bug where a parsing error may leave a broken
       * node reference in node->doc->children.
       *
       * https://bugzilla.gnome.org/show_bug.cgi?id=668155
       *
       * This workaround is limited to when a parse error occurs, the document
       * went from having no children to having children, and the context node is
       * part of a document fragment.
       *
       * TODO: This was fixed in libxml 2.8.0 by 71a243d
       */
      if (error != XML_ERR_OK && doc_is_empty && node->doc->children != NULL) {
        child_iter = node;
        while (child_iter->parent) {
          child_iter = child_iter->parent;
        }

        if (child_iter->type == XML_DOCUMENT_FRAG_NODE) {
          node->doc->children = NULL;
        }
      }

      /* FIXME: This probably needs to handle more constants... */
      switch (error) {
        case XML_ERR_INTERNAL_ERROR:
        case XML_ERR_NO_MEMORY:
          rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
          break;
        default:
          break;
      }

      set = xmlXPathNodeSetCreate(NULL);

      while (list) {
        tmp = list->next;
        list->next = NULL;
        xmlXPathNodeSetAddUnique(set, list);
        noko_xml_document_pin_node(list);
        list = tmp;
      }

      return noko_xml_node_set_wrap(set, doc);
    }

inspect_attributes() click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1555
    def inspect_attributes
      [:name, :namespace, :attribute_nodes, :children]
    end

keywordify(keywords) click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1504
    def keywordify(keywords)
      case keywords
      when Enumerable
        keywords
      when String
        keywords.scan(/\S+/)
      else
        raise ArgumentError,
          "Keyword attributes must be passed as either a String or an Enumerable, but received #{keywords.class}"
      end
    end

native_write_to(io, encoding, options) click to toggle source

Write this `Node` to `io` with `encoding` and `options`

    static VALUE
    native_write_to(
      VALUE self,
      VALUE io,
      VALUE encoding,
      VALUE indent_string,
      VALUE options
    )
    {
      xmlNodePtr node;
      const char *before_indent;
      xmlSaveCtxtPtr savectx;

      Noko_Node_Get_Struct(self, xmlNode, node);

      xmlIndentTreeOutput = 1;

      before_indent = xmlTreeIndentString;

      xmlTreeIndentString = StringValueCStr(indent_string);

      savectx = xmlSaveToIO(
                  (xmlOutputWriteCallback)noko_io_write,
                  (xmlOutputCloseCallback)noko_io_close,
                  (void *)io,
                  RTEST(encoding) ? StringValueCStr(encoding) : NULL,
                  (int)NUM2INT(options)
                );

      xmlSaveTree(savectx, node);
      xmlSaveClose(savectx);

      xmlTreeIndentString = before_indent;
      return io;
    }

prepend_newline?() click to toggle source

    static VALUE
    rb_prepend_newline(VALUE self)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      return should_prepend_newline(node) ? Qtrue : Qfalse;
    }

process_xincludes(options) click to toggle source

Loads and substitutes all xinclude elements below the node. The parser context will be initialized with `options`.

    static VALUE
    process_xincludes(VALUE self, VALUE options)
    {
      int rcode ;
      xmlNodePtr node;
      VALUE error_list = rb_ary_new();

      Noko_Node_Get_Struct(self, xmlNode, node);

      xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
      rcode = xmlXIncludeProcessTreeFlags(node, (int)NUM2INT(options));
      xmlSetStructuredErrorFunc(NULL, NULL);

      if (rcode < 0) {
        xmlErrorPtr error;

        error = xmlGetLastError();
        if (error) {
          rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
        } else {
          rb_raise(rb_eRuntimeError, "Could not perform xinclude substitution");
        }
      }

      return self;
    }

[]=(property, value) click to toggle source

Set the `property` to `value`

    static VALUE
    set(VALUE self, VALUE property, VALUE value)
    {
      xmlNodePtr node, cur;
      xmlAttrPtr prop;
      Noko_Node_Get_Struct(self, xmlNode, node);

      /* If a matching attribute node already exists, then xmlSetProp will destroy
       * the existing node's children. However, if Nokogiri has a node object
       * pointing to one of those children, we are left with a broken reference.
       *
       * We can avoid this by unlinking these nodes first.
       */
      if (node->type != XML_ELEMENT_NODE) {
        return (Qnil);
      }
      prop = xmlHasProp(node, (xmlChar *)StringValueCStr(property));
      if (prop && prop->children) {
        for (cur = prop->children; cur; cur = cur->next) {
          if (cur->_private) {
            noko_xml_document_pin_node(cur);
            xmlUnlinkNode(cur);
          }
        }
      }

      xmlSetProp(node, (xmlChar *)StringValueCStr(property),
                 (xmlChar *)StringValueCStr(value));

      return value;
    }

set_namespace(namespace) click to toggle source

Set the namespace to `namespace`

    static VALUE
    set_namespace(VALUE self, VALUE namespace)
    {
      xmlNodePtr node;
      xmlNsPtr ns = NULL;

      Noko_Node_Get_Struct(self, xmlNode, node);

      if (!NIL_P(namespace)) {
        Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
      }

      xmlSetNs(node, ns);

      return self;
    }

to_format(save_option, options) click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1541
    def to_format(save_option, options)
      return dump_html if USING_LIBXML_WITH_BROKEN_SERIALIZATION

      options[:save_with] = save_option unless options[:save_with]
      serialize(options)
    end

write_format_to(save_option, io, options) click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1548
    def write_format_to(save_option, io, options)
      return (io << dump_html) if USING_LIBXML_WITH_BROKEN_SERIALIZATION

      options[:save_with] ||= save_option
      write_to(io, options)
    end

## Manipulating Document Structure

↑ top

### Public Instance Methods

<<(node_or_tags) click to toggle source

Add `node_or_tags` as a child of this `Node`.

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String containing markup.

Returns `self`, to support chaining of calls (e.g., root << child1 << child2)

Also see related method `add_child`.

    # File lib/nokogiri/xml/node.rb, line 256
    def <<(node_or_tags)
      add_child(node_or_tags)
      self
    end

add_child(node_or_tags) click to toggle source

Add `node_or_tags` as a child of this `Node`.

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String containing markup.

Returns the reparented node (if `node_or_tags` is a `Node`), or `NodeSet` (if `node_or_tags` is a `DocumentFragment`, `NodeSet`, or String).

Also see related method +<<+.

    # File lib/nokogiri/xml/node.rb, line 148
    def add_child(node_or_tags)
      node_or_tags = coerce(node_or_tags)
      if node_or_tags.is_a?(XML::NodeSet)
        node_or_tags.each { |n| add_child_node_and_reparent_attrs(n) }
      else
        add_child_node_and_reparent_attrs(node_or_tags)
      end
      node_or_tags
    end

add_namespace(prefix, href) → Nokogiri::XML::Namespace
Alias for: add_namespace_definition
add_namespace_definition(prefix, href) → Nokogiri::XML::Namespace click to toggle source

Adds a namespace definition to this node with `prefix` using `href` value, as if this node had included an attribute “xmlns:prefix=href”.

A default namespace definition for this node can be added by passing `nil` for `prefix`.

Parameters

- `prefix` (String, `nil`) An XML Name

- `href` (String) The URI reference

Returns

  The new `Nokogiri::XML::Namespace`

Example: adding a non-default namespace definition

    doc = Nokogiri::XML("<store><inventory></inventory></store>")
    inventory = doc.at_css("inventory")
    inventory.add_namespace_definition("automobile", "http://alices-autos.com/")
    inventory.add_namespace_definition("bicycle", "http://bobs-bikes.com/")
    inventory.add_child("<automobile:tire>Michelin model XGV, size 75R</automobile:tire>")
    doc.to_xml
    # => "<?xml version=\"1.0\"?>\n" +
    #    "<store>\n" +
    #    "  <inventory xmlns:automobile=\"http://alices-autos.com/\" xmlns:bicycle=\"http://bobs-bikes.com/\">\n" +
    #    "    <automobile:tire>Michelin model XGV, size 75R</automobile:tire>\n" +
    #    "  </inventory>\n" +
    #    "</store>\n"

Example: adding a default namespace definition

    doc = Nokogiri::XML("<store><inventory><tire>Michelin model XGV, size 75R</tire></inventory></store>")
    doc.at_css("tire").add_namespace_definition(nil, "http://bobs-bikes.com/")
    doc.to_xml
    # => "<?xml version=\"1.0\"?>\n" +
    #    "<store>\n" +
    #    "  <inventory>\n" +
    #    "    <tire xmlns=\"http://bobs-bikes.com/\">Michelin model XGV, size 75R</tire>\n" +
    #    "  </inventory>\n" +
    #    "</store>\n"

    static VALUE
    rb_xml_node_add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
    {
      xmlNodePtr c_node, element;
      xmlNsPtr c_namespace;
      const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));

      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
      element = c_node ;

      c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);

      if (!c_namespace) {
        if (c_node->type != XML_ELEMENT_NODE) {
          element = c_node->parent;
        }
        c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
      }

      if (!c_namespace) {
        return Qnil ;
      }

      if (NIL_P(rb_prefix) || c_node != element) {
        xmlSetNs(c_node, c_namespace);
      }

      return noko_xml_namespace_wrap(c_namespace, c_node->doc);
    }

Also aliased as: add_namespace
add_next_sibling(node_or_tags) click to toggle source

Insert `node_or_tags` after this `Node` (as a sibling).

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String containing markup.

Returns the reparented node (if `node_or_tags` is a `Node`), or `NodeSet` (if `node_or_tags` is a `DocumentFragment`, `NodeSet`, or String).

Also see related method `after`.

    # File lib/nokogiri/xml/node.rb, line 288
    def add_next_sibling(node_or_tags)
      raise ArgumentError,
        "A document may not have multiple root nodes." if parent&.document? && !(node_or_tags.comment? || node_or_tags.processing_instruction?)

      add_sibling(:next, node_or_tags)
    end

Also aliased as: next=
add_previous_sibling(node_or_tags) click to toggle source

Insert `node_or_tags` before this `Node` (as a sibling).

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String containing markup.

Returns the reparented node (if `node_or_tags` is a `Node`), or `NodeSet` (if `node_or_tags` is a `DocumentFragment`, `NodeSet`, or String).

Also see related method `before`.

    # File lib/nokogiri/xml/node.rb, line 271
    def add_previous_sibling(node_or_tags)
      raise ArgumentError,
        "A document may not have multiple root nodes." if parent&.document? && !(node_or_tags.comment? || node_or_tags.processing_instruction?)

      add_sibling(:previous, node_or_tags)
    end

Also aliased as: previous=
after(node_or_tags) click to toggle source

Insert `node_or_tags` after this node (as a sibling).

`node_or_tags` can be a `Nokogiri::XML::Node`, a `Nokogiri::XML::DocumentFragment`, or a String containing markup.

Returns `self`, to support chaining of calls.

Also see related method `add_next_sibling`.

    # File lib/nokogiri/xml/node.rb, line 318
    def after(node_or_tags)
      add_next_sibling(node_or_tags)
      self
    end

before(node_or_tags) click to toggle source

Insert `node_or_tags` before this node (as a sibling).

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String containing markup.

Returns `self`, to support chaining of calls.

Also see related method `add_previous_sibling`.

    # File lib/nokogiri/xml/node.rb, line 304
    def before(node_or_tags)
      add_previous_sibling(node_or_tags)
      self
    end

children=(node_or_tags) click to toggle source

Set the content for this `Node` `node_or_tags`

`node_or_tags` can be a `Nokogiri::XML::Node`, a `Nokogiri::XML::DocumentFragment`, or a String containing markup.

Also see related method `inner_html=`

    # File lib/nokogiri/xml/node.rb, line 349
    def children=(node_or_tags)
      node_or_tags = coerce(node_or_tags)
      children.unlink
      if node_or_tags.is_a?(XML::NodeSet)
        node_or_tags.each { |n| add_child_node_and_reparent_attrs(n) }
      else
        add_child_node_and_reparent_attrs(node_or_tags)
      end
    end

content=(string) click to toggle source

Set the Node’s content to a `Text` node containing `string`. The string gets `XML` escaped, not interpreted as markup.

    # File lib/nokogiri/xml/node.rb, line 411
    def content=(string)
      self.native_content = encode_special_chars(string.to_s)
    end

default_namespace=(url) click to toggle source

Adds a default namespace supplied as a string `url` href, to self. The consequence is as an xmlns attribute with supplied argument were present in parsed `XML`. A default namespace set with this method will now show up in `attributes`, but when this node is serialized to `XML` an “xmlns” attribute will appear. See also `namespace` and `namespace=`

    # File lib/nokogiri/xml/node.rb, line 427
    def default_namespace=(url)
      add_namespace_definition(nil, url)
    end

do_xinclude(options = XML::ParseOptions::DEFAULT_XML) { |options| ... } click to toggle source

Do xinclude substitution on the subtree below node. If given a block, a `Nokogiri::XML::ParseOptions` object initialized from `options`, will be passed to it, allowing more convenient modification of the parser options.

    # File lib/nokogiri/xml/node.rb, line 454
    def do_xinclude(options = XML::ParseOptions::DEFAULT_XML)
      options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
      yield options if block_given?

      # call c extension
      process_xincludes(options.to_i)
    end

inner_html=(node_or_tags) click to toggle source

Set the content for this `Node` to `node_or_tags`.

`node_or_tags` can be a `Nokogiri::XML::Node`, a `Nokogiri::XML::DocumentFragment`, or a String containing markup.

⚠ Please note that despite the name, this method will not always parse a String argument as `HTML`. A String argument will be parsed with the `DocumentFragment` parser related to this node’s document.

For example, if the document is an `HTML4::Document` then the string will be parsed as `HTML4` using `HTML4::DocumentFragment`; but if the document is an `XML::Document` then it will parse the string as `XML` using `XML::DocumentFragment`.

Also see related method `children=`

    # File lib/nokogiri/xml/node.rb, line 338
    def inner_html=(node_or_tags)
      self.children = node_or_tags
    end

name=(new_name)
Alias for: node_name=
namespace=(ns) click to toggle source

Set the default namespace on this node (as would be defined with an “xmlns=” attribute in `XML` source), as a `Namespace` object `ns`. Note that a `Namespace` added this way will NOT be serialized as an xmlns attribute for this node. You probably want `default_namespace=` instead, or perhaps `add_namespace_definition` with a nil prefix argument.

    # File lib/nokogiri/xml/node.rb, line 437
    def namespace=(ns)
      return set_namespace(ns) unless ns

      unless Nokogiri::XML::Namespace === ns
        raise TypeError, "#{ns.class} can't be coerced into Nokogiri::XML::Namespace"
      end
      if ns.document != document
        raise ArgumentError, "namespace must be declared on the same document"
      end

      set_namespace(ns)
    end

next_sibling
Alias for: next_sibling
next=(node_or_tags)
Alias for: add_next_sibling
parent=(parent_node) click to toggle source

Set the parent `Node` for this `Node`

    # File lib/nokogiri/xml/node.rb, line 417
    def parent=(parent_node)
      parent_node.add_child(self)
    end

prepend_child(node_or_tags) click to toggle source

Add `node_or_tags` as the first child of this `Node`.

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String containing markup.

Returns the reparented node (if `node_or_tags` is a `Node`), or `NodeSet` (if `node_or_tags` is a `DocumentFragment`, `NodeSet`, or String).

Also see related method `add_child`.

    # File lib/nokogiri/xml/node.rb, line 168
    def prepend_child(node_or_tags)
      if (first = children.first)
        # Mimic the error add_child would raise.
        raise "Document already has a root node" if document? && !(node_or_tags.comment? || node_or_tags.processing_instruction?)

        first.__send__(:add_sibling, :previous, node_or_tags)
      else
        add_child(node_or_tags)
      end
    end

previous_sibling
Alias for: previous_sibling
previous=(node_or_tags)
Alias for: add_previous_sibling
remove()
Alias for: unlink
replace(node_or_tags) click to toggle source

Replace this `Node` with `node_or_tags`.

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String containing markup.

Returns the reparented node (if `node_or_tags` is a `Node`), or `NodeSet` (if `node_or_tags` is a `DocumentFragment`, `NodeSet`, or String).

Also see related method `swap`.

    # File lib/nokogiri/xml/node.rb, line 369
    def replace(node_or_tags)
      raise("Cannot replace a node with no parent") unless parent

      # We cannot replace a text node directly, otherwise libxml will return
      # an internal error at parser.c:13031, I don't know exactly why
      # libxml is trying to find a parent node that is an element or document
      # so I can't tell if this is bug in libxml or not. issue #775.
      if text?
        replacee = Nokogiri::XML::Node.new("dummy", document)
        add_previous_sibling_node(replacee)
        unlink
        return replacee.replace(node_or_tags)
      end

      node_or_tags = parent.coerce(node_or_tags)

      if node_or_tags.is_a?(XML::NodeSet)
        node_or_tags.each { |n| add_previous_sibling(n) }
        unlink
      else
        replace_node(node_or_tags)
      end
      node_or_tags
    end

swap(node_or_tags) click to toggle source

Swap this `Node` for `node_or_tags`

`node_or_tags` can be a `Nokogiri::XML::Node`, a ::DocumentFragment, a ::NodeSet, or a String Containing markup.

Returns self, to support chaining of calls.

Also see related method `replace`.

    # File lib/nokogiri/xml/node.rb, line 403
    def swap(node_or_tags)
      replace(node_or_tags)
      self
    end

wrap(markup) → self click to toggle source
wrap(node) → self

Wrap this `Node` with the node parsed from `markup` or a dup of the `node`.

Parameters

- markup (String) Markup that is parsed and used as the wrapper. This node’s parent, if it exists, is used as the context node for parsing; otherwise the associated document is used. If the parsed fragment has multiple roots, the first root node is used as the wrapper.

- node (`Nokogiri::XML::Node`) An element that is ‘#dup`ed and used as the wrapper.

Returns

  `self`, to support chaining.

Also see `NodeSet#wrap`

Example with a `String` argument:

    doc = Nokogiri::HTML5(<<~HTML)
      <html><body>
        <a>asdf</a>
      </body></html>
    HTML
    doc.at_css("a").wrap("<div></div>")
    doc.to_html
    # => <html><head></head><body>
    #      <div><a>asdf</a></div>
    #    </body></html>

Example with a `Node` argument:

    doc = Nokogiri::HTML5(<<~HTML)
      <html><body>
        <a>asdf</a>
      </body></html>
    HTML
    doc.at_css("a").wrap(doc.create_element("div"))
    doc.to_html
    # <html><head></head><body>
    #   <div><a>asdf</a></div>
    # </body></html>

    # File lib/nokogiri/xml/node.rb, line 223
    def wrap(node_or_tags)
      case node_or_tags
      when String
        context_node = parent || document
        new_parent = context_node.coerce(node_or_tags).first
        if new_parent.nil?
          raise "Failed to parse '#{node_or_tags}' in the context of a '#{context_node.name}' element"
        end
      when XML::Node
        new_parent = node_or_tags.dup
      else
        raise ArgumentError, "Requires a String or Node argument, and cannot accept a #{node_or_tags.class}"
      end

      if parent
        add_next_sibling(new_parent)
      else
        new_parent.unlink
      end
      new_parent.add_child(self)

      self
    end

## Serialization and Generating Output

↑ top

### Public Instance Methods

canonicalize(mode = XML::XML_C14N_1_0, inclusive_namespaces = nil, with_comments = false) click to toggle source

    # File lib/nokogiri/xml/node.rb, line 1407
    def canonicalize(mode = XML::XML_C14N_1_0, inclusive_namespaces = nil, with_comments = false)
      c14n_root = self
      document.canonicalize(mode, inclusive_namespaces, with_comments) do |node, parent|
        tn = node.is_a?(XML::Node) ? node : parent
        tn == c14n_root || tn.ancestors.include?(c14n_root)
      end
    end

deconstruct_keys(array_of_names) → Hash click to toggle source

Returns a hash describing the `Node`, to use in pattern matching.

Valid keys and their values:

- `name` → (String) The name of this node, or “text” if it is a `Text` node.

- `namespace` → (`Namespace`, nil) The namespace of this node, or nil if there is no namespace.

- `attributes` → (Array<Attr>) The attributes of this node.

- `children` → (Array<Node>) The children of this node. 💡 Note this includes text nodes.

- `elements` → (Array<Node>) The child elements of this node. 💡 Note this does not include text nodes.

- `content` → (String) The contents of all the text nodes in this node’s subtree. See `content`.

- `inner_html` → (String) The inner markup for the children of this node. See `inner_html`.

⚡ This is an experimental feature, available since v1.14.0

Example

    doc = Nokogiri::XML.parse(<<~XML)
      <?xml version="1.0"?>
      <parent xmlns="http://nokogiri.org/ns/default" xmlns:noko="http://nokogiri.org/ns/noko">
        <child1 foo="abc" noko:bar="def">First</child1>
        <noko:child2 foo="qwe" noko:bar="rty">Second</noko:child2>
      </parent>
    XML

    doc.root.deconstruct_keys([:name, :namespace])
    # => {:name=>"parent",
    #     :namespace=>
    #      #(Namespace:0x35c { href = "http://nokogiri.org/ns/default" })}

    doc.root.deconstruct_keys([:inner_html, :content])
    # => {:content=>"\n" + "  First\n" + "  Second\n",
    #     :inner_html=>
    #      "\n" +
    #      "  <child1 foo=\"abc\" noko:bar=\"def\">First</child1>\n" +
    #      "  <noko:child2 foo=\"qwe\" noko:bar=\"rty\">Second</noko:child2>\n"}

    doc.root.elements.first.deconstruct_keys([:attributes])
    # => {:attributes=>
    #      [#(Attr:0x370 { name = "foo", value = "abc" }),
    #       #(Attr:0x384 {
    #         name = "bar",
    #         namespace = #(Namespace:0x398 {
    #           prefix = "noko",
    #           href = "http://nokogiri.org/ns/noko"
    #           }),
    #         value = "def"
    #         })]}

    # File lib/nokogiri/xml/node.rb, line 1468
    def deconstruct_keys(keys)
      requested_keys = DECONSTRUCT_KEYS & keys
      {}.tap do |values|
        requested_keys.each do |key|
          method = DECONSTRUCT_METHODS[key] || key
          values[key] = send(method)
        end
      end
    end

serialize(*args, &block) click to toggle source

Serialize `Node` using `options`. Save options can also be set using a block.

See also `Nokogiri::XML::Node::SaveOptions` and Serialization and Generating Output at `Node`.

These two statements are equivalent:

    node.serialize(encoding: 'UTF-8', save_with: FORMAT | AS_XML)

or

    node.serialize(encoding: 'UTF-8') do |config|
      config.format.as_xml
    end

    # File lib/nokogiri/xml/node.rb, line 1280
    def serialize(*args, &block)
      options = if args.first.is_a?(Hash)
        args.shift
      else
        {
          encoding: args[0],
          save_with: args[1],
        }
      end

      options[:encoding] ||= document.encoding
      encoding = Encoding.find(options[:encoding] || "UTF-8")

      io = StringIO.new(String.new(encoding: encoding))

      write_to(io, options, &block)
      io.string
    end

to_html(options = {}) click to toggle source

Serialize this `Node` to `HTML`

    doc.to_html

See `Node#write_to` for a list of `options`. For formatted output, use `Node#to_xhtml` instead.

    # File lib/nokogiri/xml/node.rb, line 1306
    def to_html(options = {})
      to_format(SaveOptions::DEFAULT_HTML, options)
    end

to_xhtml(options = {}) click to toggle source

Serialize this `Node` to XHTML using `options`

    doc.to_xhtml(indent: 5, encoding: 'UTF-8')

See `Node#write_to` for a list of `options`

    # File lib/nokogiri/xml/node.rb, line 1327
    def to_xhtml(options = {})
      to_format(SaveOptions::DEFAULT_XHTML, options)
    end

to_xml(options = {}) click to toggle source

Serialize this `Node` to `XML` using `options`

    doc.to_xml(indent: 5, encoding: 'UTF-8')

See `Node#write_to` for a list of `options`

    # File lib/nokogiri/xml/node.rb, line 1316
    def to_xml(options = {})
      options[:save_with] ||= SaveOptions::DEFAULT_XML
      serialize(options)
    end

write_html_to(io, options = {}) click to toggle source

Write `Node` as `HTML` to `io` with `options`

See `Node#write_to` for a list of `options`

    # File lib/nokogiri/xml/node.rb, line 1384
    def write_html_to(io, options = {})
      write_format_to(SaveOptions::DEFAULT_HTML, io, options)
    end

write_to(io, *options) click to toggle source

Serialize this node or document to `io`.

Parameters

- `io` (IO) An IO-like object to which the serialized content will be written.

- `options` (Hash) See below

Options

- `:encoding` (String or Encoding) specify the encoding of the output (defaults to document encoding)

- `:indent_text` (String) the indentation text (defaults to `" "`)

- `:indent` (Integer) the number of `:indent_text` to use (defaults to `2`)

- `:save_with` (Integer) a combination of `SaveOptions` constants

To save with UTF-8 indented twice:

    node.write_to(io, encoding: 'UTF-8', indent: 2)

To save indented with two dashes:

    node.write_to(io, indent_text: '-', indent: 2)

    # File lib/nokogiri/xml/node.rb, line 1355
    def write_to(io, *options)
      options = options.first.is_a?(Hash) ? options.shift : {}
      encoding = options[:encoding] || options[0] || document.encoding
      if Nokogiri.jruby?
        save_options = options[:save_with] || options[1]
        indent_times = options[:indent] || 0
      else
        save_options = options[:save_with] || options[1] || SaveOptions::FORMAT
        indent_times = options[:indent] || 2
      end
      indent_text = options[:indent_text] || " "

      # Any string times 0 returns an empty string. Therefore, use the same
      # string instead of generating a new empty string for every node with
      # zero indentation.
      indentation = indent_times.zero? ? "" : (indent_text * indent_times)

      config = SaveOptions.new(save_options.to_i)
      yield config if block_given?

      encoding = encoding.is_a?(Encoding) ? encoding.name : encoding

      native_write_to(io, encoding, indentation, config.options)
    end

write_xhtml_to(io, options = {}) click to toggle source

Write `Node` as XHTML to `io` with `options`

See `Node#write_to` for a list of `options`

    # File lib/nokogiri/xml/node.rb, line 1392
    def write_xhtml_to(io, options = {})
      write_format_to(SaveOptions::DEFAULT_XHTML, io, options)
    end

write_xml_to(io, options = {}) click to toggle source

Write `Node` as `XML` to `io` with `options`

    doc.write_xml_to io, :encoding => 'UTF-8'

See `Node#write_to` for a list of options

    # File lib/nokogiri/xml/node.rb, line 1402
    def write_xml_to(io, options = {})
      options[:save_with] ||= SaveOptions::DEFAULT_XML
      write_to(io, options)
    end

## Traversing Document Structure

↑ top

### Public Instance Methods

child() → Nokogiri::XML::Node click to toggle source

Returns

  First of this node’s children, or `nil` if there are no children

This is a convenience method and is equivalent to:

    node.children.first

See related: `children`

    static VALUE
    rb_xml_node_child(VALUE self)
    {
      xmlNodePtr node, child;
      Noko_Node_Get_Struct(self, xmlNode, node);

      child = node->children;
      if (!child) { return Qnil; }

      return noko_xml_node_wrap(Qnil, child);
    }

children() → Nokogiri::XML::NodeSet click to toggle source

Returns

  `Nokogiri::XML::NodeSet` containing this node’s children.

    static VALUE
    rb_xml_node_children(VALUE self)
    {
      xmlNodePtr node;
      xmlNodePtr child;
      xmlNodeSetPtr set;
      VALUE document;
      VALUE node_set;

      Noko_Node_Get_Struct(self, xmlNode, node);

      child = node->children;
      set = xmlXPathNodeSetCreate(child);

      document = DOC_RUBY_OBJECT(node->doc);

      if (!child) { return noko_xml_node_set_wrap(set, document); }

      child = child->next;
      while (NULL != child) {
        xmlXPathNodeSetAddUnique(set, child);
        child = child->next;
      }

      node_set = noko_xml_node_set_wrap(set, document);

      return node_set;
    }

document() → Nokogiri::XML::Document click to toggle source

Returns

  Parent `Nokogiri::XML::Document` for this node

    static VALUE
    rb_xml_node_document(VALUE self)
    {
      xmlNodePtr node;
      Noko_Node_Get_Struct(self, xmlNode, node);
      return DOC_RUBY_OBJECT(node->doc);
    }

## Working With Node Attributes

↑ top

### Public Instance Methods

[](name) → (String, nil) click to toggle source

Fetch an attribute from this node.

⚠ Note that attributes with namespaces cannot be accessed with this method. To access namespaced attributes, use `attribute_with_ns`.

Returns

  (String, nil) value of the attribute `name`, or `nil` if no matching attribute exists

Example

    doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
    child = doc.at_css("child")
    child["size"] # => "large"
    child["class"] # => "big wide tall"

Example: Namespaced attributes will not be returned.

⚠ Note namespaced attributes may be accessed with `attribute` or `attribute_with_ns`

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns:width='http://example.com/widths'>
        <child width:size='broad'/>
      </root>
    EOF
    doc.at_css("child")["size"] # => nil
    doc.at_css("child").attribute("size").value # => "broad"
    doc.at_css("child").attribute_with_ns("size", "http://example.com/widths").value
    # => "broad"

    # File lib/nokogiri/xml/node.rb, line 512
    def [](name)
      get(name.to_s)
    end

Also aliased as: get_attribute, attr
[]=(name, value) → value click to toggle source

Update the attribute `name` to `value`, or create the attribute if it does not exist.

⚠ Note that attributes with namespaces cannot be accessed with this method. To access namespaced attributes for update, use `attribute_with_ns`. To add a namespaced attribute, see the example below.

Returns

  `value`

Example

    doc = Nokogiri::XML("<root><child/></root>")
    child = doc.at_css("child")
    child["size"] = "broad"
    child.to_html
    # => "<child size=\"broad\"></child>"

Example: Add a namespaced attribute.

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns:width='http://example.com/widths'>
        <child/>
      </root>
    EOF
    child = doc.at_css("child")
    child["size"] = "broad"
    ns = doc.root.namespace_definitions.find { |ns| ns.prefix == "width" }
    child.attribute("size").namespace = ns
    doc.to_html
    # => "<root xmlns:width=\"http://example.com/widths\">\n" +
    #    "  <child width:size=\"broad\"></child>\n" +
    #    "</root>\n"

    # File lib/nokogiri/xml/node.rb, line 550
    def []=(name, value)
      set(name.to_s, value.to_s)
    end

Also aliased as: set_attribute
add_class(names) → self click to toggle source

Ensure `HTML` `CSS` classes are present on `self`. Any `CSS` classes in `names` that already exist in the “class” attribute are not added. Note that any existing duplicates in the “class” attribute are not removed. Compare with `append_class`.

This is a convenience function and is equivalent to:

    node.kwattr_add("class", names)

See related: `kwattr_add`, `classes`, `append_class`, `remove_class`

Parameters

- `names` (String, Array<String>)

  `CSS` class names to be added to the Node’s “class” attribute. May be a string containing whitespace-delimited names, or an Array of String names. Any class names already present will not be added. Any class names not present will be added. If no “class” attribute exists, one is created.

Returns

  `self` (`Node`) for ease of chaining method calls.

Example: Ensure that the node has `CSS` class “section”

    node                      # => <div></div>
    node.add_class("section") # => <div class="section"></div>
    node.add_class("section") # => <div class="section"></div> # duplicate not added

Example: Ensure that the node has `CSS` classes “section” and “header”, via a String argument

Note that the `CSS` class “section” is not added because it is already present. Note also that the pre-existing duplicate `CSS` class “section” is not removed.

    node                             # => <div class="section section"></div>
    node.add_class("section header") # => <div class="section section header"></div>

Example: Ensure that the node has `CSS` classes “section” and “header”, via an Array argument

    node                                  # => <div></div>
    node.add_class(["section", "header"]) # => <div class="section header"></div>

    # File lib/nokogiri/xml/node.rb, line 715
    def add_class(names)
      kwattr_add("class", names)
    end

append_class(names) → self click to toggle source

Add `HTML` `CSS` classes to `self`, regardless of duplication. Compare with `add_class`.

This is a convenience function and is equivalent to:

    node.kwattr_append("class", names)

See related: `kwattr_append`, `classes`, `add_class`, `remove_class`

Parameters

- `names` (String, Array<String>)

  `CSS` class names to be appended to the Node’s “class” attribute. May be a string containing whitespace-delimited names, or an Array of String names. All class names passed in will be appended to the “class” attribute even if they are already present in the attribute value. If no “class” attribute exists, one is created.

Returns

  `self` (`Node`) for ease of chaining method calls.

Example: Append “section” to the node’s `CSS` “class” attribute

    node                         # => <div></div>
    node.append_class("section") # => <div class="section"></div>
    node.append_class("section") # => <div class="section section"></div> # duplicate added!

Example: Append “section” and “header” to the noded’s `CSS` “class” attribute, via a String argument

Note that the `CSS` class “section” is appended even though it is already present

    node                                # => <div class="section section"></div>
    node.append_class("section header") # => <div class="section section section header"></div>

Example: Append “section” and “header” to the node’s `CSS` “class” attribute, via an Array argument

    node                                     # => <div></div>
    node.append_class(["section", "header"]) # => <div class="section header"></div>
    node.append_class(["section", "header"]) # => <div class="section header section header"></div>

    # File lib/nokogiri/xml/node.rb, line 759
    def append_class(names)
      kwattr_append("class", names)
    end

attr(name)
Alias for: []
attribute(name) → Nokogiri::XML::Attr click to toggle source

Returns

  Attribute (`Nokogiri::XML::Attr`) belonging to this node with name `name`.

⚠ Note that attribute namespaces are ignored and only the simple (non-namespace-prefixed) name is used to find a matching attribute. In case of a simple name collision, only one of the matching attributes will be returned. In this case, you will need to use `attribute_with_ns`.

Example:

    doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
    child = doc.at_css("child")
    child.attribute("size") # => #<Nokogiri::XML::Attr:0x550 name="size" value="large">
    child.attribute("class") # => #<Nokogiri::XML::Attr:0x564 name="class" value="big wide tall">

Example showing that namespaced attributes will not be returned:

⚠ Note that only one of the two matching attributes is returned.

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns:width='http://example.com/widths'
            xmlns:height='http://example.com/heights'>
        <child width:size='broad' height:size='tall'/>
      </root>
    EOF
    doc.at_css("child").attribute("size")
    # => #(Attr:0x550 {
    #      name = "size",
    #      namespace = #(Namespace:0x564 {
    #        prefix = "width",
    #        href = "http://example.com/widths"
    #        }),
    #      value = "broad"
    #      })

    static VALUE
    rb_xml_node_attribute(VALUE self, VALUE name)
    {
      xmlNodePtr node;
      xmlAttrPtr prop;
      Noko_Node_Get_Struct(self, xmlNode, node);
      prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));

      if (! prop) { return Qnil; }
      return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
    }

attribute_nodes() → Array<Nokogiri::XML::Attr> click to toggle source

Returns

  Attributes (an Array of `Nokogiri::XML::Attr`) belonging to this node.

Note that this is the preferred alternative to `attributes` when the simple (non-namespace-prefixed) attribute names may collide.

Example:

Contrast this with the colliding-name example from `attributes`.

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns:width='http://example.com/widths'
            xmlns:height='http://example.com/heights'>
        <child width:size='broad' height:size='tall'/>
      </root>
    EOF
    doc.at_css("child").attribute_nodes
    # => [#(Attr:0x550 {
    #       name = "size",
    #       namespace = #(Namespace:0x564 {
    #         prefix = "width",
    #         href = "http://example.com/widths"
    #         }),
    #       value = "broad"
    #       }),
    #     #(Attr:0x578 {
    #       name = "size",
    #       namespace = #(Namespace:0x58c {
    #         prefix = "height",
    #         href = "http://example.com/heights"
    #         }),
    #       value = "tall"
    #       })]

    static VALUE
    rb_xml_node_attribute_nodes(VALUE rb_node)
    {
      xmlNodePtr c_node;

      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

      return noko_xml_node_attrs(c_node);
    }

attribute_with_ns(name, namespace) → Nokogiri::XML::Attr click to toggle source

Returns

  Attribute (`Nokogiri::XML::Attr`) belonging to this node with matching `name` and `namespace`.

- `name` (String): the simple (non-namespace-prefixed) name of the attribute

- `namespace` (String): the URI of the attribute’s namespace

See related: `attribute`

Example:

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns:width='http://example.com/widths'
            xmlns:height='http://example.com/heights'>
        <child width:size='broad' height:size='tall'/>
      </root>
    EOF
    doc.at_css("child").attribute_with_ns("size", "http://example.com/widths")
    # => #(Attr:0x550 {
    #      name = "size",
    #      namespace = #(Namespace:0x564 {
    #        prefix = "width",
    #        href = "http://example.com/widths"
    #        }),
    #      value = "broad"
    #      })
    doc.at_css("child").attribute_with_ns("size", "http://example.com/heights")
    # => #(Attr:0x578 {
    #      name = "size",
    #      namespace = #(Namespace:0x58c {
    #        prefix = "height",
    #        href = "http://example.com/heights"
    #        }),
    #      value = "tall"
    #      })

    static VALUE
    rb_xml_node_attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
    {
      xmlNodePtr node;
      xmlAttrPtr prop;
      Noko_Node_Get_Struct(self, xmlNode, node);
      prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
                          NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));

      if (! prop) { return Qnil; }
      return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
    }

attributes() → Hash<String ⇒ Nokogiri::XML::Attr> click to toggle source

Fetch this node’s attributes.

⚠ Because the keys do not include any namespace information for the attribute, in case of a simple name collision, not all attributes will be returned. In this case, you will need to use `attribute_nodes`.

Returns

  Hash containing attributes belonging to `self`. The hash keys are String attribute names (without the namespace), and the hash values are `Nokogiri::XML::Attr`.

Example with no namespaces:

    doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
    doc.at_css("child").attributes
    # => {"size"=>#(Attr:0x550 { name = "size", value = "large" }),
    #     "class"=>#(Attr:0x564 { name = "class", value = "big wide tall" })}

Example with a namespace:

    doc = Nokogiri::XML("<root xmlns:desc='http://example.com/sizes'><child desc:size='large'/></root>")
    doc.at_css("child").attributes
    # => {"size"=>
    #      #(Attr:0x550 {
    #        name = "size",
    #        namespace = #(Namespace:0x564 {
    #          prefix = "desc",
    #          href = "http://example.com/sizes"
    #          }),
    #        value = "large"
    #        })}

Example with an attribute name collision:

⚠ Note that only one of the attributes is returned in the Hash.

    doc = Nokogiri::XML(<<~EOF)
      <root xmlns:width='http://example.com/widths'
            xmlns:height='http://example.com/heights'>
        <child width:size='broad' height:size='tall'/>
      </root>
    EOF
    doc.at_css("child").attributes
    # => {"size"=>
    #      #(Attr:0x550 {
    #        name = "size",
    #        namespace = #(Namespace:0x564 {
    #          prefix = "height",
    #          href = "http://example.com/heights"
    #          }),
    #        value = "tall"
    #        })}

    # File lib/nokogiri/xml/node.rb, line 609
    def attributes
      attribute_nodes.each_with_object({}) do |node, hash|
        hash[node.node_name] = node
      end
    end

classes() → Array<String> click to toggle source

Fetch `CSS` class names of a `Node`.

This is a convenience function and is equivalent to:

    node.kwattr_values("class")

See related: `kwattr_values`, `add_class`, `append_class`, `remove_class`

Returns

  The `CSS` classes (Array of String) present in the Node’s “class” attribute. If the attribute is empty or non-existent, the return value is an empty array.

Example

    node         # => <div class="section title header"></div>
    node.classes # => ["section", "title", "header"]

    # File lib/nokogiri/xml/node.rb, line 669
    def classes
      kwattr_values("class")
    end

delete(name)
Alias for: remove_attribute
each() { |node_name, value| ... } click to toggle source

Iterate over each attribute name and value pair for this `Node`.

    # File lib/nokogiri/xml/node.rb, line 635
    def each
      attribute_nodes.each do |node|
        yield [node.node_name, node.value]
      end
    end

get_attribute(name)
Alias for: []
has_attribute?(p1)
Alias for: key?
keys() click to toggle source

Get the attribute names for this `Node`.

    # File lib/nokogiri/xml/node.rb, line 629
    def keys
      attribute_nodes.map(&:node_name)
    end

kwattr_add(attribute_name, keywords) → self click to toggle source

Ensure that values are present in a keyword attribute.

Any values in `keywords` that already exist in the Node’s attribute values are not added. Note that any existing duplicates in the attribute values are not removed. Compare with `kwattr_append`.

A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the `HTML` “class” attribute used to contain `CSS` classes. But other keyword attributes exist, for instance the “rel” attribute.

See also `add_class`, `kwattr_values`, `kwattr_append`, `kwattr_remove`

Parameters

- `attribute_name` (String) The name of the keyword attribute to be modified.

- `keywords` (String, Array<String>) Keywords to be added to the attribute named `attribute_name`. May be a string containing whitespace-delimited values, or an Array of String values. Any values already present will not be added. Any values not present will be added. If the named attribute does not exist, it is created.

Returns

  `self` (`Nokogiri::XML::Node`) for ease of chaining method calls.

Example: Ensure that a `Node` has “nofollow” in its `rel` attribute.

Note that duplicates are not added.

    node                               # => <a></a>
    node.kwattr_add("rel", "nofollow") # => <a rel="nofollow"></a>
    node.kwattr_add("rel", "nofollow") # => <a rel="nofollow"></a>

Example: Ensure that a `Node` has “nofollow” and “noreferrer” in its `rel` attribute, via a String argument.

    Note that "nofollow" is not added because it is already present. Note also that the
    pre-existing duplicate "nofollow" is not removed.

     node                                          # => <a rel="nofollow nofollow"></a>
     node.kwattr_add("rel", "nofollow noreferrer") # => <a rel="nofollow nofollow noreferrer"></a>

Example: Ensure that a `Node` has “nofollow” and “noreferrer” in its `rel` attribute, via an Array argument.

    node                                               # => <a></a>
    node.kwattr_add("rel", ["nofollow", "noreferrer"]) # => <a rel="nofollow noreferrer"></a>

Since v1.11.0

    # File lib/nokogiri/xml/node.rb, line 892
    def kwattr_add(attribute_name, keywords)
      keywords = keywordify(keywords)
      current_kws = kwattr_values(attribute_name)
      new_kws = (current_kws + (keywords - current_kws)).join(" ")
      set_attribute(attribute_name, new_kws)
      self
    end

kwattr_append(attribute_name, keywords) → self click to toggle source

Add keywords to a Node’s keyword attribute, regardless of duplication. Compare with `kwattr_add`.

A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the `HTML` “class” attribute used to contain `CSS` classes. But other keyword attributes exist, for instance the “rel” attribute.

See also `append_class`, `kwattr_values`, `kwattr_add`, `kwattr_remove`

Parameters

- `attribute_name` (String) The name of the keyword attribute to be modified.

- `keywords` (String, Array<String>) Keywords to be added to the attribute named `attribute_name`. May be a string containing whitespace-delimited values, or an Array of String values. All values passed in will be appended to the named attribute even if they are already present in the attribute. If the named attribute does not exist, it is created.

Returns

  `self` (`Node`) for ease of chaining method calls.

Example: Append “nofollow” to the `rel` attribute.

Note that duplicates are added.

    node                                  # => <a></a>
    node.kwattr_append("rel", "nofollow") # => <a rel="nofollow"></a>
    node.kwattr_append("rel", "nofollow") # => <a rel="nofollow nofollow"></a>

Example: Append “nofollow” and “noreferrer” to the `rel` attribute, via a String argument.

Note that “nofollow” is appended even though it is already present.

    node                                             # => <a rel="nofollow"></a>
    node.kwattr_append("rel", "nofollow noreferrer") # => <a rel="nofollow nofollow noreferrer"></a>

Example: Append “nofollow” and “noreferrer” to the `rel` attribute, via an Array argument.

    node                                                  # => <a></a>
    node.kwattr_append("rel", ["nofollow", "noreferrer"]) # => <a rel="nofollow noreferrer"></a>

Since v1.11.0

    # File lib/nokogiri/xml/node.rb, line 945
    def kwattr_append(attribute_name, keywords)
      keywords = keywordify(keywords)
      current_kws = kwattr_values(attribute_name)
      new_kws = (current_kws + keywords).join(" ")
      set_attribute(attribute_name, new_kws)
      self
    end

kwattr_remove(attribute_name, keywords) → self click to toggle source

Remove keywords from a keyword attribute. Any matching keywords that exist in the named attribute are removed, including any multiple entries.

If no keywords remain after this operation, or if `keywords` is `nil`, the attribute is deleted from the node.

A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the `HTML` “class” attribute used to contain `CSS` classes. But other keyword attributes exist, for instance the “rel” attribute.

See also `remove_class`, `kwattr_values`, `kwattr_add`, `kwattr_append`

Parameters

- `attribute_name` (String) The name of the keyword attribute to be modified.

- `keywords` (String, Array<String>) Keywords to be removed from the attribute named `attribute_name`. May be a string containing whitespace-delimited values, or an Array of String values. Any keywords present in the named attribute will be removed. If no keywords remain, or if `keywords` is nil, the attribute is deleted.

Returns

  `self` (`Node`) for ease of chaining method calls.

Example:

Note that the `rel` attribute is deleted when empty.

    node                                    # => <a rel="nofollow noreferrer">link</a>
    node.kwattr_remove("rel", "nofollow")   # => <a rel="noreferrer">link</a>
    node.kwattr_remove("rel", "noreferrer") # => <a>link</a>

Since v1.11.0

    # File lib/nokogiri/xml/node.rb, line 988
    def kwattr_remove(attribute_name, keywords)
      if keywords.nil?
        remove_attribute(attribute_name)
        return self
      end

      keywords = keywordify(keywords)
      current_kws = kwattr_values(attribute_name)
      new_kws = current_kws - keywords
      if new_kws.empty?
        remove_attribute(attribute_name)
      else
        set_attribute(attribute_name, new_kws.join(" "))
      end
      self
    end

kwattr_values(attribute_name) → Array<String> click to toggle source

Fetch values from a keyword attribute of a `Node`.

A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the `HTML` “class” attribute used to contain `CSS` classes. But other keyword attributes exist, for instance the “rel” attribute.

See also `classes`, `kwattr_add`, `kwattr_append`, `kwattr_remove`

Parameters

- `attribute_name` (String) The name of the keyword attribute to be inspected.

Returns

  (Array<String>) The values present in the Node’s `attribute_name` attribute. If the attribute is empty or non-existent, the return value is an empty array.

Example:

    node                      # => <a rel="nofollow noopener external">link</a>
    node.kwattr_values("rel") # => ["nofollow", "noopener", "external"]

Since v1.11.0

    # File lib/nokogiri/xml/node.rb, line 838
    def kwattr_values(attribute_name)
      keywordify(get_attribute(attribute_name) || [])
    end

remove_attribute(name) click to toggle source

Remove the attribute named `name`

    # File lib/nokogiri/xml/node.rb, line 643
    def remove_attribute(name)
      attr = attributes[name].remove if key?(name)
      clear_xpath_context if Nokogiri.jruby?
      attr
    end

Also aliased as: delete
remove_class(css_classes) → self click to toggle source

Remove `HTML` `CSS` classes from this node. Any `CSS` class names in `css_classes` that exist in this node’s “class” attribute are removed, including any multiple entries.

If no `CSS` classes remain after this operation, or if `css_classes` is `nil`, the “class” attribute is deleted from the node.

This is a convenience function and is equivalent to:

    node.kwattr_remove("class", css_classes)

Also see `kwattr_remove`, `classes`, `add_class`, `append_class`

Parameters

- `css_classes` (String, Array<String>)

  `CSS` class names to be removed from the Node’s “class” attribute. May be a string containing whitespace-delimited names, or an Array of String names. Any class names already present will be removed. If no `CSS` classes remain, the “class” attribute is deleted.

Returns

  `self` (`Nokogiri::XML::Node`) for ease of chaining method calls.

Example: Deleting a `CSS` class

Note that all instances of the class “section” are removed from the “class” attribute.

    node                         # => <div class="section header section"></div>
    node.remove_class("section") # => <div class="header"></div>

Example: Deleting the only remaining `CSS` class

Note that the attribute is removed once there are no remaining classes.

    node                         # => <div class="section"></div>
    node.remove_class("section") # => <div></div>

Example: Deleting multiple `CSS` classes

Note that the “class” attribute is deleted once it’s empty.

    node                                    # => <div class="section header float"></div>
    node.remove_class(["section", "float"]) # => <div class="header"></div>

    # File lib/nokogiri/xml/node.rb, line 809
    def remove_class(names = nil)
      kwattr_remove("class", names)
    end

[]=(name, value) → value
Alias for: []=
value?(value) click to toggle source

Does this Node’s attributes include <value>

    # File lib/nokogiri/xml/node.rb, line 623
    def value?(value)
      values.include?(value)
    end

values() click to toggle source

Get the attribute values for this `Node`.

    # File lib/nokogiri/xml/node.rb, line 617
    def values
      attribute_nodes.map(&:value)
    end