Skip to content

[bug] XSLT empty-string document('') should refer to the stylesheet, not ENOENT #3517

@doriantaylor

Description

@doriantaylor

I just upgraded Nokogiri to 1.18.8 and it seems that the empty-string document('') construct in XSLT now raises a RuntimeError:

RuntimeError: I/O warning : failed to load "": No such file or directory

    /var/lib/gems/3.3.0/gems/nokogiri-1.18.8-x86_64-linux-gnu/lib/nokogiri/xslt/stylesheet.rb:45:in `transform'                                                
    /var/lib/gems/3.3.0/gems/nokogiri-1.18.8-x86_64-linux-gnu/lib/nokogiri/xslt/stylesheet.rb:45:in `apply_to'                                                 
    /home/dorian/experimental/nokogiri-empty-document.rb:43:in `block (2 levels) in <class:Test>'                                                              

This script will replicate:

#! /usr/bin/env ruby

require 'nokogiri'
require 'minitest/autorun'

class Test < Minitest::Spec
  XSLT = Nokogiri::XSLT.parse <<~EOS
  <?xml version="1.0"?>
  <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:html="http://www.w3.org/1999/xhtml"
     xmlns="http://www.w3.org/1999/xhtml"
     xmlns:x="urn:x-dummy"
     exclude-result-prefixes="html x">

  <x:foo>THIS SHOULD WORK LOL</x:foo>

  <xsl:template match="html:body">
  <body>
    <h1><xsl:value-of select="document('')/xsl:stylesheet/x:foo[1]"/></h1>
  </body>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{name()}" namespace="{namespace-uri()}">

      <xsl:for-each select="@*">
        <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
          <xsl:value-of select="."/>
        </xsl:attribute>
      </xsl:for-each>

      <xsl:apply-templates/>

    </xsl:element>
  </xsl:template>

  </xsl:stylesheet>
  EOS

  DOC = Nokogiri.XML <<~EOS
  <?xml version="1.0"?>
  <!DOCTYPE html>
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
      <title>help computer</title>
    </head>
    <body>
      <p>this should be replaced</p>
    </body>
  </html>
  EOS

  describe "XSLT#transform" do
    it "should correctly treat the special case of document('')" do

      doc = XSLT.transform DOC

      assert_equal 'THIS SHOULD WORK LOL',
        doc.at_xpath('/html:html/html:body/html:h1[1]',
                     { html: 'http://www.w3.org/1999/xhtml' }).text
    end
  end
end

Expected behavior

The XSLT 1.0 spec stipulates that document('') is supposed to refer to the root node of the stylesheet itself:

Note that a zero-length URI reference is a reference to the document relative to which the URI reference is being resolved; thus document("") refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document.

Environment

# Nokogiri (1.18.8)
    ---
    warnings: []
    nokogiri:
      version: 1.18.8
      cppflags:
      - "-I/var/lib/gems/3.3.0/gems/nokogiri-1.18.8-x86_64-linux-gnu/ext/nokogiri"                                                                             
      - "-I/var/lib/gems/3.3.0/gems/nokogiri-1.18.8-x86_64-linux-gnu/ext/nokogiri/include"                                                                     
      - "-I/var/lib/gems/3.3.0/gems/nokogiri-1.18.8-x86_64-linux-gnu/ext/nokogiri/include/libxml2"                                                             
      ldflags: []
    ruby:
      version: 3.3.7
      platform: x86_64-linux-gnu
      gem_platform: x86_64-linux-gnu
      description: ruby 3.3.7 (2025-01-15 revision be31f993d7) [x86_64-linux-gnu]                                                                              
      engine: ruby
    libxml:
      source: packaged
      precompiled: true
      patches:
      - 0001-Remove-script-macro-support.patch
      - 0002-Update-entities-to-remove-handling-of-ssi.patch
      - '0009-allow-wildcard-namespaces.patch'
      - 0010-update-config.guess-and-config.sub-for-libxml2.patch
      - 0011-rip-out-libxml2-s-libc_single_threaded-support.patch
      - '0019-xpath-Use-separate-static-hash-table-for-standard-fu.patch'
      memory_management: ruby
      iconv_enabled: true
      compiled: 2.13.8
      loaded: 2.13.8
    libxslt:
      source: packaged
      precompiled: true
      patches:
      - 0001-update-config.guess-and-config.sub-for-libxslt.patch
      datetime_enabled: true
      compiled: 1.1.43
      loaded: 1.1.43
    other_libraries:
      zlib: 1.3.1
      libgumbo: 1.0.0-nokogiri

Additional context

It had previously been working for years?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions