nokogiri

package module
v0.0.0-...-32139ec Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: BSD-3-Clause Imports: 11 Imported by: 0

README

go-ruby-nokogiri/nokogiri

nokogiri — go-ruby-nokogiri

Docs License Go Coverage

A pure-Go (no cgo) reimplementation of the core of Ruby's Nokogiri HTML/XML toolkit. Upstream Nokogiri is a C extension over libxml2 and libxslt; this library instead builds on the pure-Go golang.org/x/net/html tag-soup parser (for Nokogiri::HTML) and Go's encoding/xml (for Nokogiri::XML), exposes a single mutable Node tree over both, and layers a full XPath 1.0 engine plus a CSS-selector → XPath compiler on top — so css / at_css / xpath / at_xpath behave as Ruby programs expect, with CGO_ENABLED=0 on every supported platform.

It is the HTML/XML backend for go-embedded-ruby, but is a standalone, reusable Go module with no dependency on the Ruby runtime — a sibling of go-ruby-rexml (the pure-Ruby REXML parser). Where REXML implements a small XML DOM with an XPath subset, this library targets the Nokogiri API surface and a fuller XPath 1.0.

Architecture

Four layers, deliberately kept independent:

  1. HTML5 parserNokogiri::HTML(str) runs the lenient WHATWG HTML5 tree-building algorithm via x/net/html. Real-world "tag soup" is recovered exactly as a browser would: implied <html>/<head>/<body>, inferred end tags, misnested-tag correction. This is Nokogiri's #1 use.
  2. XML parserNokogiri::XML(str) parses well-formed XML via encoding/xml (RawToken mode), resolving namespace prefixes to URIs while preserving the literal prefix for round-tripping, and recovering CDATA node types that encoding/xml otherwise collapses into text.
  3. Shared Node tree — one doubly-linked, mutable DOM (Node / NodeSet / Attr) produced by both parsers and consumed by everything above.
  4. XPath 1.0 + CSS — a from-scratch XPath 1.0 engine (all 13 axes, node tests, predicates, and the core function library) and a CSS-selector→XPath translator, both operating on the shared tree.

Features

  • Parse: Nokogiri::HTML / Nokogiri::HTML5 / Nokogiri::XML / HTML fragments → Document. XML declarations are recognised (version/encoding preserved for round-tripping; ASCII-compatible non-UTF-8 declarations parse structurally — see the deferred note on charset transcoding).
  • Navigate: children / element_children / parent / next / previous / next_element / previous_element / root.
  • Query: css / at_css / xpath / at_xpath on Node, Document, and NodeSet; raw scalar XPath results (count(), string(), …) via EvalXPath.
  • CSS selectors: type / * / #id / .class; [attr] and [attr=val] with the ~= |= ^= $= *= variants; descendant / child (>) / adjacent (+) / general-sibling (~) combinators; structural pseudo-classes :first-child :last-child :only-child :empty :root :nth-child(An+B|odd|even) :nth-last-child :first-of-type :last-of-type :nth-of-type :only-of-type :not(...); selector lists (a, b).
  • XPath 1.0: axes child descendant descendant-or-self self parent ancestor ancestor-or-self following-sibling preceding-sibling following preceding attribute namespace; node tests node() text() comment() processing-instruction() and name tests (with namespace prefixes); predicates with position/last(); the core library (last position count id local-name name namespace-uri string concat starts-with contains substring-before substring-after substring string-length normalize-space translate boolean not true false lang number sum floor ceiling round, plus current()); the full operator set (or and = != < <= > >= + - * div mod |).
  • Text & serialization: text / content / inner_html / inner_xml / to_html / to_xml / to_s. to_xml reproduces libxml2's exact pretty-printing — the two-space indent, the XML declaration + trailing newline at the document level, and the sticky-downward rule that leaves a subtree inline once any level holds character data — all pinned byte-for-byte against the gem. to_html follows WHATWG/HTML5 serialization (void elements without /, raw-text script/style left unescaped, empty non-void elements as <x></x>, no added whitespace). Correct entity escaping; [] / attribute / set_attribute / remove_attribute / name / node-type predicates.
  • Namespaces: namespaces (full in-scope map, nearest-wins), namespace (the node's own prefix/URI), and add_namespace_definition (AddNamespace) with live re-resolution of the affected subtree.
  • Streaming SAX: Nokogiri::XML::SAX::Parser / SAX::Document — a SAXHandler interface (embed SAXDocument for no-op defaults) driven over Parse/ParseReader, firing start_document / end_document / start_element (attributes including xmlns in source order) / end_element / characters / comment / cdata_block / processing_instruction / error, with the event stream pinned against the gem's SAX parser.
  • Build & mutate: Nokogiri::XML::Builder-style programmatic construction; add_child / prepend / add_next_sibling / add_previous_sibling / remove / replace / wrap / content=.

What it is — and isn't (deferred, documented honestly)

The following are not implemented and are called out so nothing is a silent gap. They are the parts of Nokogiri that go well beyond parse + query + serialize

  • stream, or that depend on libxslt/libxml2 subsystems:
  • XSLT (Nokogiri::XSLT) — not built in here; a pure-Go XSLT 1.0 processor lives in the sibling module go-ruby-xslt/xslt, which drives this library's XPath engine through the XPathContext extension seam (Node.EvalXPathCtx).
  • Schema validation — no DTD / RelaxNG / XSD (Nokogiri::XML::Schema, RelaxNG) validation. These are large, self-contained validators that in the reference implementation are libxml2's schema engines; reproducing them in pure Go is out of scope for this module and is named, not half-shipped.
  • Pull ReaderNokogiri::XML::Reader (cursor-style pull parsing) is not provided; use the event-driven SAX::Parser (implemented) or the DOM.
  • HTML SAXNokogiri::HTML4::SAX::Parser is not provided; SAX streaming is XML-only. (HTML is still fully supported via the DOM parser.)
  • Exact libxml2 error recovery / diagnostics — malformed input is reported through the error callback / a returned error, but the text of libxml2's messages (e.g. "Opening and ending tag mismatch: … line N") and its precise fault-tolerant recovery of broken XML are genuinely libxml2 behaviour and are not reproduced.
  • Charset transcoding — a non-UTF-8 XML declaration is honoured for round-tripping (the encoding is preserved on to_xml) and ASCII-compatible encodings parse structurally, but the byte stream is not transcoded to UTF-8 the way libxml2 does; genuinely non-ASCII-compatible encodings are not supported.

The focus is squarely parse → CSS/XPath → navigate → serialize → stream (SAX), which covers the overwhelming majority of scraping and document-processing code.

Install

go get github.com/go-ruby-nokogiri/nokogiri

Usage

package main

import (
	"fmt"

	nokogiri "github.com/go-ruby-nokogiri/nokogiri"
)

func main() {
	doc, _ := nokogiri.HTML(`<html><body>
	  <ul class="list">
	    <li class="item">Alpha</li>
	    <li class="item">Beta</li>
	  </ul>
	  <a href="https://example.com">link</a>
	</body></html>`)

	// CSS
	doc.CSS("ul.list li.item")             // NodeSet of the two <li>
	first, _ := doc.AtCSS("li.item")       // -> <li>Alpha</li>
	fmt.Println(first.Text())              // "Alpha"

	// XPath 1.0
	set, _ := doc.XPath("//a[starts-with(@href,'https')]")
	fmt.Println(set.First().Attribute("href")) // "https://example.com"

	n, _ := doc.Node.EvalXPath("count(//li)", nil)
	fmt.Println(n) // 2

	// Build
	b := nokogiri.NewBuilder()
	b.Element("catalog", func(b *nokogiri.Builder) {
		b.Element("book", func(b *nokogiri.Builder) {
			b.Attr("id", "b1")
			b.ElementText("title", "Alpha")
		})
	})
	fmt.Println(b.ToXML())
	// <catalog><book id="b1"><title>Alpha</title></book></catalog>
}

Tests & coverage

The suite holds 100.0% statement coverage with zero dependency on a Ruby runtime — the deterministic, golden-vector tests alone drive the gate, so the Windows and cross-arch (qemu) CI lanes pass without ruby installed. A separate differential oracle compares parse + css/xpath results, to_xml/to_html serialized bytes, namespaces, and the SAX event stream against the real nokogiri gem on the ubuntu/macos lanes (skipped where ruby is absent, and version-gated to RUBY_VERSION >= "4.0").

GOWORK=off go test -race -cover ./...

CI validates on 3 OSes (Linux/macOS/Windows) and 6 64-bit architectures (amd64, arm64, riscv64, loong64, ppc64le, s390x). The host -race lane keeps cgo enabled; the architecture lanes build with CGO_ENABLED=0.

License

BSD-3-Clause © the go-ruby-nokogiri/nokogiri authors. See LICENSE.

WebAssembly

Being pure Go (CGO=0), this library also compiles to WebAssembly — both GOOS=js GOARCH=wasm (browser / Node.js) and GOOS=wasip1 GOARCH=wasm (WASI). CI builds both targets on every push, alongside the six 64-bit native/qemu arches.

GOOS=js     GOARCH=wasm go build ./...   # browser / Node
GOOS=wasip1 GOARCH=wasm go build ./...   # WASI (wasmtime, wasmer, wasmedge, …)

Documentation

Overview

Package nokogiri is a pure-Go (no cgo) reimplementation of the core of Ruby's Nokogiri HTML/XML toolkit. Nokogiri is normally a C extension over libxml2 and libxslt; this library instead builds on the pure-Go golang.org/x/net/html tag-soup parser (for Nokogiri::HTML) and encoding/xml (for Nokogiri::XML), exposes a single Node tree over both, and layers an XPath 1.0 engine plus a CSS-selector-to-XPath compiler on top so that at_css/css/at_xpath/xpath behave as Ruby programs expect — all with CGO_ENABLED=0.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Attr

type Attr struct {
	Name      string
	Value     string
	Prefix    string
	Namespace string
}

Attr is a single attribute on an element. Namespace holds the resolved namespace URI when the attribute is namespaced (empty otherwise); Prefix holds the literal prefix as written (e.g. "xml" for xml:lang).

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder programmatically constructs an XML (or HTML) document tree, the Go analogue of Nokogiri::XML::Builder. Where Ruby leans on method_missing and blocks, this exposes an explicit, chainable API: Element opens a child element, runs the supplied closure to populate it, and closes it; Text/Comment/CDATA add leaf nodes; Attr sets an attribute on the current element.

func NewBuilder

func NewBuilder() *Builder

NewBuilder starts a new XML document builder.

func NewHTMLBuilder

func NewHTMLBuilder() *Builder

NewHTMLBuilder starts a new HTML document builder (HTML serialization rules).

func (*Builder) Attr

func (b *Builder) Attr(name, value string) *Builder

Attr sets an attribute on the current element.

func (*Builder) CDATA

func (b *Builder) CDATA(s string) *Builder

CDATA appends a CDATA node to the current element.

func (*Builder) Comment

func (b *Builder) Comment(s string) *Builder

Comment appends a comment node to the current element.

func (*Builder) Document

func (b *Builder) Document() *Document

Document returns the built document.

func (*Builder) Element

func (b *Builder) Element(name string, fn func(*Builder)) *Builder

Element opens a child element named name under the current node, invokes fn (if non-nil) with the builder positioned inside it, then restores the previous current node. Returns the builder for chaining.

func (*Builder) ElementText

func (b *Builder) ElementText(name, text string) *Builder

ElementText is the common leaf case: an element whose only content is text.

func (*Builder) Root

func (b *Builder) Root() *Node

Root returns the document's root element (nil until one is added).

func (*Builder) Text

func (b *Builder) Text(s string) *Builder

Text appends a text node to the current element.

func (*Builder) ToHTML

func (b *Builder) ToHTML() string

ToHTML serializes the built document with HTML rules.

func (*Builder) ToXML

func (b *Builder) ToXML() string

ToXML serializes the built document with XML rules.

type Document

type Document struct {
	Node
	// contains filtered or unexported fields
}

Document is the root of a parsed tree. It embeds a Node (the DocumentNode) and records whether it came from the HTML or the XML parser, which controls default serialization (HTML void elements, etc.).

func HTML

func HTML(s string) (*Document, error)

HTML parses a real-world HTML document with the lenient, HTML5 tree-building algorithm (via the pure-Go golang.org/x/net/html parser), matching Nokogiri::HTML / Nokogiri::HTML5. Malformed "tag soup" is recovered exactly as a browser would: missing end tags are inferred, misnested tags are corrected, and implied <html>/<head>/<body> wrappers are added.

func HTML5

func HTML5(s string) (*Document, error)

HTML5 parses an HTML document with the WHATWG HTML5 algorithm, matching Nokogiri::HTML5. Because golang.org/x/net/html already implements the HTML5 tree-building specification, this is the same code path as HTML; the alias exists so ported Ruby that calls Nokogiri::HTML5(...) reads naturally.

func HTMLFragment

func HTMLFragment(s string) (*Document, error)

HTMLFragment parses a fragment of HTML with no implied document wrappers, matching Nokogiri::HTML::DocumentFragment.parse. The returned Document's children are the fragment's top-level nodes.

func HTMLFragmentReader

func HTMLFragmentReader(r io.Reader) (*Document, error)

HTMLFragmentReader is HTMLFragment reading from an io.Reader.

func HTMLReader

func HTMLReader(r io.Reader) (*Document, error)

HTMLReader is HTML reading from an io.Reader (Nokogiri accepts an IO too).

func NewDocument

func NewDocument() *Document

NewDocument creates an empty XML Document to hold a freshly built tree, such as an XSLT result tree. Its root is a DocumentNode; append the result with AddChild.

func XML

func XML(s string) (*Document, error)

XML parses a well-formed XML document into the shared Node tree, matching Nokogiri::XML. Namespaces are resolved: an element or attribute in a namespace carries its resolved URI, and the literal prefix as written is preserved for round-tripping. Unlike Nokogiri::HTML this path is strict; a malformed document returns an error.

func (*Document) AtCSS

func (d *Document) AtCSS(selector string) (*Node, error)

AtCSS runs a CSS query and returns the first match.

func (*Document) AtXPath

func (d *Document) AtXPath(expr string) (*Node, error)

AtXPath runs an XPath query and returns the first match.

func (*Document) CSS

func (d *Document) CSS(selector string) (*NodeSet, error)

CSS runs a CSS query against the document root (Nokogiri::XML::Document#css).

func (*Document) NewCDATA

func (d *Document) NewCDATA(s string) *Node

NewCDATA creates a detached CDATA node (Nokogiri::XML::Document#create_cdata).

func (*Document) NewComment

func (d *Document) NewComment(s string) *Node

NewComment creates a detached comment node (Nokogiri::XML::Document#create_comment).

func (*Document) NewElement

func (d *Document) NewElement(name string) *Node

NewElement creates a detached element node named name owned by the document, mirroring Nokogiri::XML::Document#create_element.

func (*Document) NewPI

func (d *Document) NewPI(name, data string) *Node

NewPI creates a detached processing-instruction node with target name and the given data (Nokogiri::XML::ProcessingInstruction.new). XSLT builds these for xsl:processing-instruction.

func (*Document) NewText

func (d *Document) NewText(s string) *Node

NewText creates a detached text node (Nokogiri::XML::Document#create_text_node).

func (*Document) XPath

func (d *Document) XPath(expr string) (*NodeSet, error)

XPath runs an XPath query against the document (Nokogiri::XML::Document#xpath).

type Namespace

type Namespace struct {
	Prefix string // "" for the default namespace
	URI    string
}

Namespace is an in-scope xmlns declaration visible from a node.

type Node

type Node struct {
	Type NodeType

	// name is the element/PI/attribute name (local part kept in Name, prefix in
	// Prefix). For text/comment/cdata nodes it is the libxml2 pseudo-name
	// ("text", "comment", "#cdata-section").
	Name   string
	Prefix string // namespace prefix as written, e.g. "svg" in <svg:rect>
	NsURI  string // resolved namespace URI for this element, if any

	Attrs []*Attr
	// contains filtered or unexported fields
}

Node is the shared DOM node produced by BOTH the HTML and the XML parsers and consumed by the XPath and CSS engines. It is a mutable, doubly-linked tree: a node knows its parent, first/last child, and previous/next sibling. The public method set mirrors the slice of Nokogiri::XML::Node that this library targets.

func (*Node) AddChild

func (n *Node) AddChild(child *Node) *Node

AddChild appends child as the last child of n (Nokogiri::XML::Node#add_child / #<<). If child already has a parent it is detached first. Returns child.

func (*Node) AddNamespace

func (n *Node) AddNamespace(prefix, uri string) *Namespace

AddNamespace declares an xmlns mapping on n (an empty prefix sets the default namespace) and returns it, mirroring Nokogiri::XML::Node#add_namespace_definition. If the same prefix is already declared on n its URI is updated in place. The declaration takes effect for the node's own resolution and for its descendants.

func (*Node) AddNextSibling

func (n *Node) AddNextSibling(sib *Node) *Node

AddNextSibling inserts sib immediately after n (Nokogiri#add_next_sibling).

func (*Node) AddPreviousSibling

func (n *Node) AddPreviousSibling(sib *Node) *Node

AddPreviousSibling inserts sib immediately before n (Nokogiri#add_previous_sibling).

func (*Node) AtCSS

func (n *Node) AtCSS(selector string, nsMap map[string]string) (*Node, error)

AtCSS returns the first node matching the CSS selector, or nil (Nokogiri#at_css).

func (*Node) AtXPath

func (n *Node) AtXPath(expr string, nsMap map[string]string) (*Node, error)

AtXPath returns the first node matching the XPath expression, or nil (Nokogiri#at_xpath).

func (*Node) Attribute

func (n *Node) Attribute(name string) string

Attribute returns the value of the named attribute, or "" if absent. This is the ergonomic form of Nokogiri#[]/#attr.

func (*Node) Attributes

func (n *Node) Attributes() map[string]*Attr

Attributes returns the node's attributes keyed by their qualified name, matching Nokogiri::XML::Node#attributes (best effort; last write wins on a duplicate qualified name).

func (*Node) CSS

func (n *Node) CSS(selector string, nsMap map[string]string) (*NodeSet, error)

CSS evaluates one or more comma-separated CSS selectors against n and returns the matching nodes (Nokogiri::XML::Node#css). Selectors are translated to XPath and evaluated over the descendant axis rooted at n.

func (*Node) Children

func (n *Node) Children() *NodeSet

Children returns the element/text/comment children as a NodeSet.

func (*Node) Content

func (n *Node) Content() string

Content is an alias for Text (Nokogiri#content).

func (*Node) Document

func (n *Node) Document() *Document

Document returns the owning document.

func (*Node) ElementChildren

func (n *Node) ElementChildren() *NodeSet

ElementChildren returns only the element children (Nokogiri#element_children).

func (*Node) EvalXPath

func (n *Node) EvalXPath(expr string, nsMap map[string]string) (any, error)

EvalXPath evaluates expr and returns the raw XPath object (a *NodeSet, string, float64, or bool), matching how Nokogiri returns scalar results for functions like count()/string(). Node-sets are wrapped as *NodeSet.

func (*Node) EvalXPathCtx

func (n *Node) EvalXPathCtx(expr string, nsMap map[string]string, ctx *XPathContext) (any, error)

EvalXPathCtx evaluates expr against n with the variable bindings and extension-function resolver carried by ctx (which may be nil). Node-sets are returned as *NodeSet; scalar results as string, float64 or bool — the same object model as EvalXPath.

func (*Node) FirstChild

func (n *Node) FirstChild() *Node

FirstChild returns the first child node, or nil.

func (*Node) Get

func (n *Node) Get(name string) (string, bool)

Get returns the value of the named attribute and whether it was present. The lookup matches on the qualified name as written (prefix:local) first, then on the bare local name, mirroring Nokogiri::XML::Node#[].

func (*Node) HasAttribute

func (n *Node) HasAttribute(name string) bool

HasAttribute reports whether the named attribute is present.

func (*Node) InnerHTML

func (n *Node) InnerHTML() string

InnerHTML serializes the node's children with HTML rules (Nokogiri#inner_html). Children of a raw-text element (script/style/…) are emitted verbatim, matching WHATWG serialization.

func (*Node) InnerXML

func (n *Node) InnerXML() string

InnerXML serializes the node's children with XML rules (no pretty-printing).

func (*Node) IsCDATA

func (n *Node) IsCDATA() bool

IsCDATA reports whether n is a CDATA node.

func (*Node) IsComment

func (n *Node) IsComment() bool

IsComment reports whether n is a comment node.

func (*Node) IsElement

func (n *Node) IsElement() bool

IsElement reports whether n is an element node.

func (*Node) IsText

func (n *Node) IsText() bool

IsText reports whether n is a text or CDATA node.

func (*Node) LastChild

func (n *Node) LastChild() *Node

LastChild returns the last child node, or nil.

func (*Node) Namespace

func (n *Node) Namespace() *Namespace

Namespace returns the namespace this node itself belongs to (its resolved prefix and URI), or nil when the node is not in any namespace — mirroring Nokogiri::XML::Node#namespace.

func (*Node) NamespaceDeclarations

func (n *Node) NamespaceDeclarations() []*Namespace

NamespaceDeclarations returns the xmlns declarations introduced on this node.

func (*Node) Namespaces

func (n *Node) Namespaces() map[string]string

Namespaces returns every xmlns declaration in scope at n — the node's own declarations plus those inherited from its ancestors, nearest first — keyed the way Nokogiri::XML::Node#namespaces keys them: "xmlns" for the default namespace and "xmlns:<prefix>" for a prefixed one. When a prefix is redeclared on a nearer ancestor, the nearer declaration wins (and appears in its position). The implicit "xml" namespace is not included, matching Nokogiri.

func (*Node) Next

func (n *Node) Next() *Node

Next returns the next sibling node, or nil. Named to mirror Nokogiri#next.

func (*Node) NextElement

func (n *Node) NextElement() *Node

NextElement returns the next sibling that is an element (Nokogiri#next_element).

func (*Node) NodeName

func (n *Node) NodeName() string

NodeName returns the libxml2/Nokogiri node name: the qualified tag name for elements, or a pseudo-name for the other node types.

func (*Node) NodeType

func (n *Node) NodeType() NodeType

NodeType returns the node's kind.

func (*Node) Parent

func (n *Node) Parent() *Node

Parent returns the node's parent, or nil at the document root.

func (*Node) Prepend

func (n *Node) Prepend(child *Node) *Node

Prepend inserts child as the first child of n (Nokogiri#prepend_child).

func (*Node) Previous

func (n *Node) Previous() *Node

Previous returns the previous sibling node, or nil.

func (*Node) PreviousElement

func (n *Node) PreviousElement() *Node

PreviousElement returns the previous element sibling.

func (*Node) Remove

func (n *Node) Remove()

Remove detaches n from its tree (Nokogiri::XML::Node#remove / #unlink).

func (*Node) RemoveAttribute

func (n *Node) RemoveAttribute(name string)

RemoveAttribute deletes the named attribute if present (Nokogiri#remove_attribute).

func (*Node) Replace

func (n *Node) Replace(repl *Node) *Node

Replace swaps n out for repl in the tree (Nokogiri::XML::Node#replace).

func (*Node) Root

func (n *Node) Root() *Node

Root returns the document's root element (the first element child of the document node), reached from any node.

func (*Node) SetAttribute

func (n *Node) SetAttribute(name, value string)

SetAttribute sets (or creates) the named attribute, matching Nokogiri::XML::Node#set_attribute / #[]=.

func (*Node) SetContent

func (n *Node) SetContent(s string)

SetContent replaces all children of n with a single text node holding s (Nokogiri::XML::Node#content=).

func (*Node) Text

func (n *Node) Text() string

Text returns the concatenated character data of the node and all descendants, matching Nokogiri#text / #content / #inner_text.

func (*Node) ToHTML

func (n *Node) ToHTML() string

ToHTML serializes the node using HTML rules (Nokogiri#to_html). HTML output is not pretty-printed (WHATWG serialization adds no whitespace).

func (*Node) ToS

func (n *Node) ToS() string

ToS serializes the node using the owning document's default (HTML rules for an HTML document, XML rules otherwise), matching Nokogiri#to_s.

func (*Node) ToXML

func (n *Node) ToXML() string

ToXML serializes the node using XML rules (Nokogiri#to_xml), reproducing libxml2's indentation. A DocumentNode additionally emits the XML declaration and a trailing newline.

func (*Node) Wrap

func (n *Node) Wrap(markup string) (*Node, error)

Wrap parses markup (a single element, using the owning document's parser) and re-parents n inside it, putting the new wrapper where n used to be — the Go analogue of Nokogiri::XML::Node#wrap. It returns the wrapper element.

func (*Node) XPath

func (n *Node) XPath(expr string, nsMap map[string]string) (*NodeSet, error)

XPath evaluates an XPath 1.0 expression against n and returns the matching nodes as a NodeSet (Nokogiri::XML::Node#xpath). Namespaces registered with nsMap (prefix->URI) are visible to prefixed name tests.

type NodeSet

type NodeSet struct {
	// contains filtered or unexported fields
}

NodeSet is an ordered collection of nodes, the analogue of Nokogiri::XML::NodeSet returned by #css / #xpath / #children.

func NewNodeSet

func NewNodeSet(nodes []*Node) *NodeSet

NewNodeSet builds a *NodeSet from a slice of nodes. XSLT uses it to hand node-set variable values and extension-function results back to the engine.

func (*NodeSet) At

func (s *NodeSet) At(i int) *Node

At returns the node at index i, or nil if out of range. Negative indices count from the end, matching Ruby's NodeSet#[].

func (*NodeSet) CSS

func (s *NodeSet) CSS(selector string) (*NodeSet, error)

CSS runs a CSS query against every node in the set and unions the results.

func (*NodeSet) Each

func (s *NodeSet) Each(fn func(*Node))

Each calls fn for every node in order.

func (*NodeSet) Empty

func (s *NodeSet) Empty() bool

Empty reports whether the set has no nodes.

func (*NodeSet) First

func (s *NodeSet) First() *Node

First returns the first node, or nil.

func (*NodeSet) Last

func (s *NodeSet) Last() *Node

Last returns the last node, or nil.

func (*NodeSet) Length

func (s *NodeSet) Length() int

Length returns the number of nodes in the set (Nokogiri#length / #size).

func (*NodeSet) Nodes

func (s *NodeSet) Nodes() []*Node

Nodes returns the underlying slice (a copy is not made; do not mutate).

func (*NodeSet) Text

func (s *NodeSet) Text() string

Text returns the concatenated text of every node in the set, matching Nokogiri::XML::NodeSet#text.

func (*NodeSet) XPath

func (s *NodeSet) XPath(expr string) (*NodeSet, error)

XPath runs an XPath query against every node in the set and unions the results.

type NodeType

type NodeType int

NodeType enumerates the node kinds Nokogiri exposes. The numeric values match libxml2's node type constants that Nokogiri surfaces through Node#type so that ported Ruby code comparing against Nokogiri::XML::Node::ELEMENT_NODE (== 1) and friends keeps working.

const (
	// ElementNode is a tag such as <div> or <book>.
	ElementNode NodeType = 1
	// AttributeNode is an attribute; only produced when an attribute is exposed
	// as a node (e.g. via an XPath attribute axis result).
	AttributeNode NodeType = 2
	// TextNode is character data between tags.
	TextNode NodeType = 3
	// CDATANode is a <![CDATA[ ... ]]> section.
	CDATANode NodeType = 4
	// CommentNode is an <!-- ... --> comment.
	CommentNode NodeType = 8
	// DocumentNode is the root document container.
	DocumentNode NodeType = 9
	// DoctypeNode is a <!DOCTYPE ...> declaration.
	DoctypeNode NodeType = 10
	// ProcessingInstructionNode is a <?target data?> instruction.
	ProcessingInstructionNode NodeType = 7
)

type SAXDocument

type SAXDocument struct{}

SAXDocument provides no-op implementations of every SAXHandler callback, so a handler need only embed it and override the events it cares about — the Go equivalent of subclassing Nokogiri::XML::SAX::Document.

func (SAXDocument) CdataBlock

func (SAXDocument) CdataBlock(string)

CdataBlock is a no-op default.

func (SAXDocument) Characters

func (SAXDocument) Characters(string)

Characters is a no-op default.

func (SAXDocument) Comment

func (SAXDocument) Comment(string)

Comment is a no-op default.

func (SAXDocument) EndDocument

func (SAXDocument) EndDocument()

EndDocument is a no-op default.

func (SAXDocument) EndElement

func (SAXDocument) EndElement(string)

EndElement is a no-op default.

func (SAXDocument) Error

func (SAXDocument) Error(string)

Error is a no-op default.

func (SAXDocument) ProcessingInstruction

func (SAXDocument) ProcessingInstruction(string, string)

ProcessingInstruction is a no-op default.

func (SAXDocument) StartDocument

func (SAXDocument) StartDocument()

StartDocument is a no-op default.

func (SAXDocument) StartElement

func (SAXDocument) StartElement(string, []*Attr)

StartElement is a no-op default.

type SAXHandler

type SAXHandler interface {
	// StartDocument fires once before any other event.
	StartDocument()
	// EndDocument fires once after the last event of a successful parse.
	EndDocument()
	// StartElement fires at an element's start tag. name is the qualified name
	// (prefix:local) as written; attrs lists every attribute in source order,
	// including xmlns declarations, matching the non-namespaced start_element.
	StartElement(name string, attrs []*Attr)
	// EndElement fires at an element's end tag (or the implied end of an
	// empty-element tag).
	EndElement(name string)
	// Characters fires for a run of ordinary character data.
	Characters(text string)
	// Comment fires for a comment's content.
	Comment(text string)
	// CdataBlock fires for the content of a CDATA section.
	CdataBlock(text string)
	// ProcessingInstruction fires for a <?target data?> instruction (the XML
	// declaration is not reported).
	ProcessingInstruction(target, data string)
	// Error fires when the parse cannot continue; the parse then stops.
	Error(message string)
}

SAXHandler receives streaming parse events, the Go analogue of a Nokogiri::XML::SAX::Document subclass. Every method is a callback; embed SAXDocument to get no-op defaults and override only what you need.

type SAXParser

type SAXParser struct {
	// contains filtered or unexported fields
}

SAXParser drives a SAXHandler over an XML source, mirroring Nokogiri::XML::SAX::Parser. Parsing is event-driven; no DOM is built.

func NewSAXParser

func NewSAXParser(h SAXHandler) *SAXParser

NewSAXParser returns a parser that dispatches events to h.

func (*SAXParser) Parse

func (p *SAXParser) Parse(s string) error

Parse streams s through the handler (Nokogiri::XML::SAX::Parser#parse).

func (*SAXParser) ParseReader

func (p *SAXParser) ParseReader(r io.Reader) error

ParseReader reads all of r, then streams it through the handler. libxml2's SAX is incremental; the whole source is buffered here so CDATA sections can be told apart from ordinary text, which needs the raw bytes.

type XPathContext

type XPathContext struct {
	// Vars binds $name references. A value may be a *NodeSet, string, float64 or
	// bool; other numeric/int kinds are coerced to float64 by NewXPathValue.
	Vars map[string]any

	// ResolveFunc, when non-nil, is consulted for any function call the built-in
	// XPath library does not implement. It receives the function's already-evaluated
	// arguments (each a *NodeSet, string, float64 or bool) and returns the result
	// plus ok=true, or ok=false to fall through to the built-in "unknown function"
	// error. This is where XSLT plugs key(), format-number(), and friends.
	ResolveFunc func(name string, args []any) (result any, ok bool)

	// Current overrides the node returned by current(). When nil, current() yields
	// the context node the expression is evaluated against (the default behaviour).
	Current *Node

	// Position and Size seed the context position()/last() of the outermost
	// expression. XSLT sets them to the processing position and size of the node
	// being handled (e.g. inside xsl:for-each). When Position is 0 the defaults
	// (1 and 1) are used, matching a bare EvalXPath.
	Position int
	Size     int
}

XPathContext supplies variable bindings and an extension-function resolver to an XPath evaluation. A nil *XPathContext behaves exactly like Node.EvalXPath.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL