Compare commits

...

25 Commits

Author SHA1 Message Date
rulingcom dbcf687fdd test 2024-02-15 14:17:27 +08:00
rulingcom 47238a8c7b Support older ruby 2.1. 2024-02-15 13:07:07 +08:00
Yorick Peterse c4efbcec1b
Release 3.4 2022-08-02 16:18:22 +02:00
lulalala 0a9d6302c3 Take ownership when children nodes are assigned 2022-08-02 21:17:33 +08:00
lulalala 36c11b2712 Update owner when assign children 2022-07-13 21:34:08 +08:00
Yorick Peterse cf27b764e8
Release 3.3 2020-07-27 02:20:04 +02:00
Roy Zwambag 2142243227 Add to_s as an alias to the to_xml method 2020-07-27 00:14:36 +00:00
Roy Zwambag 5bdd0207a0 Small fixes in CONTRIBUTING.md
- Change the links to to working links.
- Rename "pull request" to "merge request".
2020-07-25 21:41:28 +02:00
Yorick Peterse b7daee79de
Updated outdated parts of the CONTRIBUTING guide 2020-02-20 17:33:43 +01:00
Yorick Peterse 6736bcaeba
Release 3.2 2020-01-10 16:03:15 +01:00
Yorick Peterse 7f5c0dc8b0
Add CI config for Ruby 2.7 2020-01-10 15:41:37 +01:00
Kitaiti Makoto b9bcd21b2b Distinguish hash argument and keyword argument in arguments of XML::Querying#xpath 2020-01-10 20:18:48 +09:00
Kitaiti Makoto 804f755101 Pass keyword argument to XML::Querying#xpath implicitly 2020-01-10 20:17:16 +09:00
Yorick Peterse ac3fe8f343
Release 3.1 2020-01-08 13:57:23 +01:00
Yorick Peterse f00fa40e3a
Make PUBLIC/SYSTEM matching case-insensitive
Some websites may use "public" or "system" in doctypes, or completely
messed up casing such as PuBlIc (unlikely, but possible). This ensures
we don't care about the exact casing used.

This fixes https://gitlab.com/yorickpeterse/oga/issues/199
2020-01-08 03:23:46 +01:00
Kitaiti Makoto 10e9101c42 Write document about XML::Queryng#xpath's namespace argument 2019-12-03 20:13:32 +09:00
Yorick Peterse f4832339b2
Release 3.0 2019-12-03 02:06:12 +01:00
Yorick Peterse bf44e357e4
Drop support for Rubinius
Rubinius hasn't been tested on for years, nor is it really relevant as a
Ruby implementation these days. While Oga probably still works fine on
Rubinius, I don't want to claim we support something when we officially
don't.
2019-12-03 01:34:26 +01:00
Yorick Peterse 82373d164f
Bump MRI requirements to 2.3.0
See https://gitlab.com/yorickpeterse/oga/issues/196 for more
information.
2019-12-03 01:33:52 +01:00
Yorick Peterse e413165afd
Release 2.17 2019-12-02 19:32:43 +01:00
KitaitiMakoto 95da93949b Fix XPath queries using default XML namespace
This fixes https://gitlab.com/yorickpeterse/oga/issues/195
2019-12-02 17:40:11 +00:00
Yorick Peterse d492a775bf
Release 2.16 2019-11-29 15:43:39 +01:00
KitaitiMakoto 977bd594c8 Add support for XPath namespace aliases
This fixes https://gitlab.com/yorickpeterse/oga/issues/176
2019-11-29 14:21:45 +00:00
Kitaiti Makoto da9721cb34 Suppress deprecation warning on RDoc
> NOTE: Gem::Specification#has_rdoc= is deprecated with no replacement. It
> will be removed on or after 2018-12-01.
2019-11-05 16:12:31 +00:00
KitaitiMakoto d9e7346b60 Fix older option for gem command 2019-11-05 12:38:17 +00:00
36 changed files with 279 additions and 54 deletions

View File

@ -3,7 +3,7 @@
before_script:
- apk add --update ragel build-base
- if [ "$INSTALL_OPENJDK" == "true" ]; then apk add openjdk8; fi
- gem install bundler --no-ri --no-rdoc
- gem install bundler --no-document
- ruby --version
- gem --version
- bundle --version
@ -14,10 +14,6 @@
paths:
- vendor/ruby
Ruby 2.2:
image: "ruby:2.2-alpine"
<<: *defaults
Ruby 2.3:
image: "ruby:2.3-alpine"
<<: *defaults
@ -26,6 +22,18 @@ Ruby 2.4:
image: "ruby:2.4-alpine"
<<: *defaults
Ruby 2.5:
image: "ruby:2.5-alpine"
<<: *defaults
Ruby 2.6:
image: "ruby:2.6-alpine"
<<: *defaults
Ruby 2.7:
image: "ruby:2.7-alpine"
<<: *defaults
JRuby 9.1:
image: "jruby:9.1-alpine"
variables:

View File

@ -3,6 +3,56 @@
This document contains details of the various releases and their release dates.
Dates are in the format `yyyy-mm-dd`.
## 3.4 - 2022-08-02
This release includes a change that when setting the child nodes of a node A,
node A takes ownership over the entire new child tree. See merge request
https://gitlab.com/yorickpeterse/oga/-/merge_requests/194 for more details.
## 3.3 - 2020-07-27
This release adds `to_s` as an alias for `to_xml`, thanks to Roy Zwambag. See
merge request https://gitlab.com/yorickpeterse/oga/-/merge_requests/192 for more
information.
## 3.2 - 2020-01-10
This release fixes a few warnings that would show up when using Oga on Ruby
2.7.0. See https://gitlab.com/yorickpeterse/oga/merge_requests/190 for more
information.
## 3.1 - 2020-01-08
This release fixes a bug in the XML lexer that prevented the parsing of doctypes
using "public" or "system" instead of "PUBLIC"/"SYSTEM". See issue
<https://gitlab.com/yorickpeterse/oga/issues/199> for more information.
## 3.0 - 2019-12-03
This release bumps the Ruby version requirement to Ruby 2.3.0, as we haven't
supported older versions for several years now. We also no longer officially
support Rubinius.
## 2.17 - 2019-12-02
Elements using the default XML namespace can now be queried using XPath queries,
which was broken for quite a while.
See commit <https://gitlab.com/yorickpeterse/oga/commit/95da93949bf613612981f5cd7decc0d2c2a60e15>
for more information.
## 2.16 - 2019-11-29
* XPath namespace aliases can now be used when querying elements using XPath
expressions.
* Several RDOc and RubyGems deprecation warnings have been resolved.
See the following commits for more information:
* <https://gitlab.com/yorickpeterse/oga/commit/d9e7346b60c3afa2b3e83a240f9807c6bb819d48>
* <https://gitlab.com/yorickpeterse/oga/commit/da9721cb34f91527e72b096c6bd6a128e37b1992>
* <https://gitlab.com/yorickpeterse/oga/commit/977bd594c8bfd1a29aeba9d3a4ab7d0ebbc7d11a>
## 2.15 - 2018-04-11
The HTML parser now allows `th` elements to occur in `thead`, `tbody`, and

View File

@ -28,7 +28,7 @@ When making changes please stick to the existing style and patterns as this
keeps the codebase consistent. If a certain pattern or style is getting in your
way please open a separate issue about this so it can be discussed.
Every commit and every pull request made is carefully reviewed. Chances are I'll
Every commit and every merge request made is carefully reviewed. Chances are I'll
spend more time reviewing it than the time an author spent on their changes.
This should ensure that Oga's codebase is stable, of high quality and easy to
maintain. As such _please_ take my feedback into consideration (or discuss it in
@ -36,18 +36,18 @@ a civilized manner) instead of just dismissing it with comments such as "But I
fixed the problem so your feedback is irrelevant" or "This is my way of doing
things".
Finally, and this will sound harsh: I will _not_ merge pull requests if the
Finally, and this will sound harsh: I will _not_ merge merge requests if the
author(s) simply disregard the feedback I've given them or if there are other
problems with the pull request. Do not expect me to just blindly accept whatever
problems with the merge request. Do not expect me to just blindly accept whatever
changes are submitted.
Some examples of good pull request:
Some examples of good merge requests:
* https://gitlab.com/yorickpeterse/oga/pull/96
* https://gitlab.com/yorickpeterse/oga/pull/67
* https://gitlab.com/yorickpeterse/ffi-aspell/pull/21
* https://gitlab.com/yorickpeterse/ffi-aspell/pull/20
* https://gitlab.com/yorickpeterse/ruby-ll/pull/16
* https://gitlab.com/yorickpeterse/oga/-/merge_requests/96
* https://gitlab.com/yorickpeterse/oga/-/merge_requests/67
* https://gitlab.com/yorickpeterse/ffi-aspell/-/merge_requests/21
* https://gitlab.com/yorickpeterse/ffi-aspell/-/merge_requests/20
* https://gitlab.com/yorickpeterse/ruby-ll/-/merge_requests/16
## Git
@ -140,19 +140,14 @@ such a case use `describe 'foo'` for class methods and `describe '#foo'` for
instance methods.
Whenever adding new specifications please keep them in the existing style. If
the style is problematic you can open a separate pull request to address it. If
the style is problematic you can open a separate merge request to address it. If
you expect this to be a lot of work you should open an issue first to discuss
things.
## Continuous Integration
Two continuous integration services are used to ensure the tests of Oga pass
at all times:
* Travis CI: <https://gitlab.com/yorickpeterse/oga/pipelines>
* AppVeyor (Windows): <https://ci.appveyor.com/project/yorickpeterse/oga>
Pull requests won't be merged if any of the builds fail unless stated otherwise.
Oga is tested using GitLab CI. Merge requests require that all tests pass before
they can be merged.
## Extension Setup
@ -219,7 +214,7 @@ modify `$LOAD_PATH`, instead run any scripts using `ruby -I lib`.
In case you have any further questions or would like to receive feedback before
submitting a change, feel free to contact me. You can either open an issue,
send a tweet to [@yorickpeterse][twitter] or send an Email to
<yorickpeterse@gmail.com>.
<yorick@yorickpeterse.com>.
[editorconfig]:http://editorconfig.org/
[twitter]: https://twitter.com/yorickpeterse

View File

@ -173,8 +173,8 @@ Querying a document using a namespace:
| Ruby | Required | Recommended |
|:---------|:--------------|:------------|
| MRI | >= 1.9.3 | >= 2.1.2 |
| Rubinius | >= 2.2 | >= 2.2.10 |
| JRuby | >= 1.7 | >= 1.7.12 |
| Rubinius | Not supported | |
| Maglev | Not supported | |
| Topaz | Not supported | |
| mruby | Not supported | |
@ -227,15 +227,14 @@ And if you want to specify an explicit namespace URI, you can use this:
descendant::*[local-name() = "bar" and namespace-uri() = "http://example.com"]
Unlike Nokogiri, Oga does _not_ provide a way to create "dynamic" namespaces.
That is, Nokogiri allows one to query the above document as following:
Like Nokogiri, Oga provides a way to create "dynamic" namespaces.
That is, Oga allows one to query the above document as following:
document = Nokogiri::XML('<root xmlns="http://example.com"><bar>bar</bar></root>')
document = Oga.parse_xml('<root xmlns="http://example.com"><bar>bar</bar></root>')
document.xpath('x:root/x:bar', :x => 'http://example.com')
document.xpath('x:root/x:bar', namespaces: {'x' => 'http://example.com'})
Oga does have a small trick you can use to cut down the size of your XPath
queries. Because Oga assigns the name "xmlns" to default namespaces you can use
Moreover, because Oga assigns the name "xmlns" to default namespaces you can use
this in your XPath queries:
document = Oga.parse_xml('<root xmlns="http://example.com"><bar>bar</bar></root>')
@ -246,9 +245,6 @@ When using this you can still restrict the query to the correct namespace URI:
document.xpath('xmlns:root[namespace-uri() = "http://example.com"]/xmlns:bar')
In the future I might add an API to ease this process, although at this time I
have little interest in providing an API similar to Nokogiri.
## HTML5 Support
Oga fully supports HTML5 including the omission of certain tags. For example,

View File

@ -0,0 +1 @@
241e4861fb8cdb8576b72672a2ad1d59e0f72333eb203d19b8922e15091a3470d0150d417f78d2394e2c9140fa7c9d87508acc51907537f57813b8c23272922e

View File

@ -0,0 +1 @@
5a2abc35e0696adf408f1d517865e49d511b26e39c0fe6a1f299baf77563327661498f3e1d70e20feb118810eb6457649706dc4fc3e8c45868d4b3d0ef56bfc8

View File

@ -0,0 +1 @@
4e35c653ef64ebfbbee7a933923e9cf53e988028e53cb1535127962d249501881ce35e5c7375b98e43e220b7561961a9d35fe15caf20b263b20367660a59b3eb

View File

@ -0,0 +1 @@
9cbb14e1abea3ebec3b7e9051bff5cae466cc4e608df6aa7826add38bcdb5b406cc8090405e63128a6902b24a64082ef5b9d1a36970c399ef4c941f63f2ee305

View File

@ -0,0 +1 @@
b64906a38edefb346c2ba9770336cb69f424e0776690932fea524f014dda00d8fe1b13b69fff1f01ca75c8f5107b92056c25f8ae7ee4aeb83770dc03b5d482c0

View File

@ -0,0 +1 @@
56eea6f76968afb2916e73d729a9c94dcacfb1cccc6fa0ef27888e6e8006a80cda9279db4b040be81b33ee354916e49e437ce0189ce79bdbab7c0f54203b9f2e

View File

@ -0,0 +1 @@
a2246547f87d1901e280d9df915bf41a6b78ac14805c5c0f471f5dd1cf617f1e5b3e4aa05e58ae5aa816e188456ccd3638e44a7aba41ed2dfb942f509b2093af

View File

@ -0,0 +1 @@
deb03862d5263b2cb47169267aa37c41be82fcb01d048d840506d2c8924fb0bba6a4407401052e8a5f42d053c2bb3410701316fe21570b35a2981850dc05a481

View File

@ -0,0 +1 @@
b0c3740f08d33f5b9a76c6532de749b8004fb591e3bd3b745e8c57a3bbc5b3d6be4c9a02432fc32f4ae3ca53b488dc409243af91e43646ba3f486fec4738911e

View File

@ -0,0 +1 @@
27f941862134b9e5fc46b33d8dd642a7c816f8b0bb6448789c5f23e9da42abdc72b19713985cf81257074931a4f51e014aa551e09bcb7858cde9987ea17aca75

View File

@ -0,0 +1 @@
c5521d5bc9e025fadfb4e0719c8ff0fa103dd7c184cdf4c60154a1bb5f7d71c9d807a84e76a21b13665de1bbe54f9ba23f6e479650b1bd497302f86ff2af8bbf

View File

@ -0,0 +1 @@
be44f4fb2f5f821306556b965a928e42753a57e489516654bdda74662058510cdc9885b50f6170f23762309f3a7c94791d8db71180272961341c917ffc3560e4

View File

@ -0,0 +1 @@
eef134163a86451be4a5ec72b262fec6a1dad10613e0d4002142b09e02cb444cc25ce018cdd62a870b266fc8dd390ba4fe110e07a2c41f50a3d8abdcc69b5dec

View File

@ -0,0 +1 @@
2ba0fdbfa3fa15b8d1ce5df4df4cfb3813f34399c93517f98ec8da1e82ff3cdc6e3543bf017b8246daa8b2521a64af92a9438a404b69da0f319272c510961314

View File

@ -289,7 +289,7 @@
# Machine for processing doctypes. Doctype values such as the public
# and system IDs are treated as T_STRING tokens.
doctype := |*
'PUBLIC' | 'SYSTEM' => {
'PUBLIC'i | 'SYSTEM'i => {
callback(id_on_doctype_type, data, encoding, ts, te);
};

View File

@ -1,3 +1,3 @@
module Oga
VERSION = '2.15'
VERSION = '3.4'
end # Oga

View File

@ -46,6 +46,8 @@ module Oga
# @param [Oga::XML::NodeSet|Array] nodes
def children=(nodes)
if nodes.is_a?(NodeSet)
nodes.owner = self
nodes.take_ownership_on_nodes
@children = nodes
else
@children = NodeSet.new(nodes, self)

View File

@ -49,6 +49,8 @@ module Oga
# @param [Oga::XML::NodeSet|Array] nodes
def children=(nodes)
if nodes.is_a?(NodeSet)
nodes.owner = self
nodes.take_ownership_on_nodes
@children = nodes
else
@children = NodeSet.new(nodes, self)

View File

@ -42,11 +42,7 @@ module Oga
@owner = owner
@existing = {}
@nodes.each_with_index do |node, index|
mark_existing(node)
take_ownership(node, index) if @owner
end
take_ownership_on_nodes
end
# Yields the supplied block for every node.
@ -289,6 +285,14 @@ module Oga
"NodeSet(#{values})"
end
def take_ownership_on_nodes
@nodes.each_with_index do |node, index|
mark_existing(node)
take_ownership(node, index) if @owner
end
end
private
# Takes ownership of the given node. This only occurs when the current

View File

@ -10,6 +10,7 @@ module Oga
# document = Oga.parse_xml <<-EOF
# <people>
# <person age="25">Alice</person>
# <ns:person xmlns:ns="http://example.net">Bob</ns:person>
# </people>
# EOF
#
@ -25,15 +26,23 @@ module Oga
#
# document.xpath('people/person[@age = $age]', 'age' => 25)
#
# Using namespace aliases:
#
# namespaces = {'example' => 'http://example.net'}
# document.xpath('people/example:person', namespaces: namespaces)
#
# @param [String] expression The XPath expression to run.
#
# @param [Hash] variables Variables to bind. The keys of this Hash should
# be String values.
#
# @param [Hash] namespaces Namespace aliases. The keys of this Hash should
# be String values.
#
# @return [Oga::XML::NodeSet]
def xpath(expression, variables = {})
def xpath(expression, variables = {}, namespaces: nil)
ast = XPath::Parser.parse_with_cache(expression)
block = XPath::Compiler.compile_with_cache(ast)
block = XPath::Compiler.compile_with_cache(ast, namespaces: namespaces)
block.call(self, variables)
end
@ -54,8 +63,8 @@ module Oga
#
# @see [#xpath]
# @return [Oga::XML::Node|Oga::XML::Attribute]
def at_xpath(*args)
result = xpath(*args)
def at_xpath(*args, namespaces: nil)
result = xpath(*args, namespaces: namespaces)
result.is_a?(XML::NodeSet) ? result.first : result
end

View File

@ -7,6 +7,8 @@ module Oga
def to_xml
Generator.new(self).to_xml
end
alias_method :to_s, :to_xml
end
end
end

View File

@ -42,12 +42,16 @@ module Oga
# Compiles and caches an AST.
#
# @see [#compile]
def self.compile_with_cache(ast)
CACHE.get_or_set(ast) { new.compile(ast) }
def self.compile_with_cache(ast, namespaces: nil)
cache_key = namespaces ? [ast, namespaces] : ast
CACHE.get_or_set(cache_key) { new(namespaces: namespaces).compile(ast) }
end
def initialize
# @param [Hash] namespaces
def initialize(namespaces: nil)
reset
@namespaces = namespaces
end
# Resets the internal state.
@ -1385,7 +1389,23 @@ module Oga
end
if ns and ns != STAR
ns_match = input.namespace_name.eq(string(ns))
if @namespaces
ns_uri = @namespaces[ns]
ns_match =
if ns_uri
input.namespace.and(input.namespace.uri.eq(string(ns_uri)))
else
self.false
end
else
ns_match =
if ns == XML::Element::XMLNS_PREFIX
input
else
input.namespace_name.eq(string(ns))
end
end
condition = condition ? condition.and(ns_match) : ns_match
end

BIN
oga-3.4.gem Normal file

Binary file not shown.

View File

@ -29,7 +29,6 @@ Gem::Specification.new do |s|
s.extensions = ['ext/c/extconf.rb']
end
s.has_rdoc = 'yard'
s.required_ruby_version = '>= 1.9.3'
s.add_dependency 'ast'

View File

@ -22,6 +22,7 @@ describe Oga::XML::Document do
document.children = [child]
expect(document.children[0]).to eq(child)
expect(document.children[0].parent).to eq(document)
end
it 'sets the child nodes using a NodeSet' do
@ -31,6 +32,7 @@ describe Oga::XML::Document do
document.children = Oga::XML::NodeSet.new([child])
expect(document.children[0]).to eq(child)
expect(document.children[0].parent).to eq(document)
end
end

View File

@ -168,5 +168,16 @@ describe Oga::XML::Generator do
end
end
end
describe 'using an Element with replaced children' do
it 'returns a string' do
element = Oga::XML::Element.new(name: 'foo')
element.children = Oga::XML::Parser.new('<bar></bar>').parse.children
output = described_class.new(element).to_xml
expect(output).to eq('<foo><bar /></foo>')
end
end
end
end

View File

@ -108,7 +108,7 @@ describe Oga::XML::Lexer do
# Technically not valid, put in place to make sure that the Ragel rules are
# not too greedy.
it 'lexes an inline doftype followed by a system ID' do
it 'lexes an inline doctype followed by a system ID' do
expect(lex('<!DOCTYPE html [<!ELEMENT foo>] "foo">')).to eq([
[:T_DOCTYPE_START, nil, 1],
[:T_DOCTYPE_NAME, 'html', 1],
@ -119,5 +119,31 @@ describe Oga::XML::Lexer do
[:T_DOCTYPE_END, nil, 1]
])
end
it 'does not care about the casing when using a public doctype' do
expect(lex('<!DoCtYpE HtMl PuBlIc [<!ELEMENT foo>] "foo">')).to eq([
[:T_DOCTYPE_START, nil, 1],
[:T_DOCTYPE_NAME, 'HtMl', 1],
[:T_DOCTYPE_TYPE, 'PuBlIc', 1],
[:T_DOCTYPE_INLINE, '<!ELEMENT foo>', 1],
[:T_STRING_DQUOTE, nil, 1],
[:T_STRING_BODY, 'foo', 1],
[:T_STRING_DQUOTE, nil, 1],
[:T_DOCTYPE_END, nil, 1]
])
end
it 'does not care about the casing when using a system doctype' do
expect(lex('<!DoCtYpE HtMl SyStEm [<!ELEMENT foo>] "foo">')).to eq([
[:T_DOCTYPE_START, nil, 1],
[:T_DOCTYPE_NAME, 'HtMl', 1],
[:T_DOCTYPE_TYPE, 'SyStEm', 1],
[:T_DOCTYPE_INLINE, '<!ELEMENT foo>', 1],
[:T_STRING_DQUOTE, nil, 1],
[:T_STRING_BODY, 'foo', 1],
[:T_STRING_DQUOTE, nil, 1],
[:T_DOCTYPE_END, nil, 1]
])
end
end
end

View File

@ -3,6 +3,10 @@ require 'spec_helper'
describe Oga::XML::Querying do
before do
@document = parse('<a>foo</a>')
@document2 = parse('<a xmlns:x="y"><x:b>bar</x:b></a>')
@namespaces = {
"n" => "y"
}
end
describe '#xpath' do
@ -15,7 +19,11 @@ describe Oga::XML::Querying do
end
it 'evaluates an expression using a variable' do
expect(@document.xpath('$number', 'number' => 10)).to eq(10)
expect(@document.xpath('$number', {'number' => 10})).to eq(10)
end
it 'respects custom namespace aliases' do
expect(@document2.xpath('a/n:b', namespaces: @namespaces)[0].text).to eq('bar')
end
end
@ -29,7 +37,11 @@ describe Oga::XML::Querying do
end
it 'evaluates an expression using a variable' do
expect(@document.at_xpath('$number', 'number' => 10)).to eq(10)
expect(@document.at_xpath('$number', {'number' => 10})).to eq(10)
end
it 'respects custom namespace aliases' do
expect(@document2.at_xpath('a/n:b', namespaces: @namespaces).text).to eq('bar')
end
end

View File

@ -0,0 +1,11 @@
require 'spec_helper'
describe Oga::XML::ToXML do
describe '#to_s' do
it 'is an alias of to_xml' do
node = Oga::XML::Element.new(name: 'foo')
expect(node.method(:to_s)).to eq(node.method(:to_xml))
end
end
end

View File

@ -0,0 +1,40 @@
require 'spec_helper'
describe Oga::XPath::Compiler do
before do
@document = parse('<root xmlns:x="y"><x:a></x:a><b x:num="10"></b></root>')
@root = @document.children[0]
@a = @root.children[0]
@b = @root.children[1]
@attr = @b.attributes[0]
@namespaces = {
"n" => "y"
}
end
describe 'with custom namespace aliases' do
it 'uses aliases when querying an element' do
expect(evaluate_xpath(@document, 'root/n:a', namespaces: @namespaces)).to eq(node_set(@a))
end
it "doesn't use namespaces in XPath expression when querying an element" do
expect(evaluate_xpath(@document, 'root/x:a', namespaces: @namespaces)).to eq(node_set)
end
it 'uses aliases when querying an attribute' do
expect(evaluate_xpath(@document, 'root/b/@n:num', namespaces: @namespaces)).to eq(node_set(@attr))
end
it "doesn't use namespaces in XPath expression when querying an attribute" do
expect(evaluate_xpath(@document, 'root/b/@x:num', namespaces: @namespaces)).to eq(node_set)
end
it 'uses aliases when querying an element with a namespaced attribute' do
expect(evaluate_xpath(@document, 'root/b[@n:num]', namespaces: @namespaces)).to eq(node_set(@b))
end
it "doesn't use namespaces in XPath expression when querying an element with a namespaced attribute" do
expect(evaluate_xpath(@document, 'root/b[@x:num]', namespaces: @namespaces)).to eq(node_set)
end
end
end

View File

@ -68,4 +68,26 @@ describe Oga::XPath::Compiler do
end
end
end
describe 'querying elements with a default namespace' do
before do
@document = parse('<a xmlns="n" xmlns:ns1="x">Foo<b></b><b></b><ns1:c></ns1:c></a>')
@a1 = @document.children[0]
@b1 = @a1.children[1]
@b2 = @a1.children[2]
end
describe '/xmlns:a' do
it 'returns a NodeSet' do
expect(evaluate_xpath(@document)).to eq(node_set(@a1))
end
end
describe '//xmlns:b' do
it 'returns a NodeSet' do
expect(evaluate_xpath(@document)).to eq(node_set(@b1, @b2))
end
end
end
end

View File

@ -5,9 +5,9 @@ module Oga
# @param [String] xpath
# @return [Oga::XML::NodeSet]
#
def evaluate_xpath(document, xpath = self.class.description)
def evaluate_xpath(document, xpath = self.class.description, namespaces: nil)
ast = parse_xpath(xpath)
compiler = Oga::XPath::Compiler.new
compiler = Oga::XPath::Compiler.new(namespaces: namespaces)
block = compiler.compile(ast)
block.call(document)