[前][次][番号順一覧][スレッド一覧]

ruby-changes:51071

From: kou <ko1@a...>
Date: Sat, 28 Apr 2018 10:36:24 +0900 (JST)
Subject: [ruby-changes:51071] kou:r63278 (trunk): rexml: disable XPath 1.0 compatible "#{ELEMENT_NAME}" processing by default

kou	2018-04-28 10:36:18 +0900 (Sat, 28 Apr 2018)

  New Revision: 63278

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63278

  Log:
    rexml: disable XPath 1.0 compatible "#{ELEMENT_NAME}" processing by default
    
    It breaks backward compatibility than I thought. So it's disabled by
    default. It means that REXML's XPath processor isn't compatible with
    XPath 1.0. But it will be acceptable for users.
    
    We can enable it by specifying "strict: true" to
    REXML::XPathParser.new explicitly.
    
    * lib/rexml/xpath.rb,
      lib/rexml/xpath_parser.rb: Accept "strict: true" option.
    
    * test/rexml/test_contrib.rb,
      test/rexml/xpath/test_base.rb: Use not XPath 1.0 compatible behavior.
    
    * test/rexml/test_jaxen.rb: Use XPath 1.0 compatible behavior.
    
    * test/rss/test_1.0.rb,
      test/rss/test_dublincore.rb,
      spec/ruby/library/rexml/element/namespace_spec.rb,
      spec/ruby/library/rexml/element/namespaces_spec.rb,
      spec/ruby/library/rexml/element/prefixes_spec.rb: Enable again.

  Modified files:
    trunk/lib/rexml/xpath.rb
    trunk/lib/rexml/xpath_parser.rb
    trunk/spec/ruby/library/rexml/element/namespace_spec.rb
    trunk/spec/ruby/library/rexml/element/namespaces_spec.rb
    trunk/spec/ruby/library/rexml/element/prefixes_spec.rb
    trunk/test/rexml/test_contrib.rb
    trunk/test/rexml/test_jaxen.rb
    trunk/test/rexml/xpath/test_base.rb
    trunk/test/rss/test_1.0.rb
    trunk/test/rss/test_dublincore.rb
Index: test/rexml/xpath/test_base.rb
===================================================================
--- test/rexml/xpath/test_base.rb	(revision 63277)
+++ test/rexml/xpath/test_base.rb	(revision 63278)
@@ -880,10 +880,12 @@ module REXMLTests https://github.com/ruby/ruby/blob/trunk/test/rexml/xpath/test_base.rb#L880
   <tada xmlns=''>xb</tada>
 </tag1>
       XML
-      x = d.root
-      num = 0
-      x.each_element('tada') {  num += 1 }
-      assert_equal(1, num)
+      actual = []
+      d.root.each_element('tada') do |element|
+        actual << element.to_s
+      end
+      assert_equal(["<tada>xa</tada>", "<tada xmlns=''>xb</tada>"],
+                   actual)
     end
 
     def test_ticket_39
Index: test/rexml/test_contrib.rb
===================================================================
--- test/rexml/test_contrib.rb	(revision 63277)
+++ test/rexml/test_contrib.rb	(revision 63278)
@@ -451,7 +451,7 @@ EOL https://github.com/ruby/ruby/blob/trunk/test/rexml/test_contrib.rb#L451
     end
 
     def test_external_entity
-      xp = '//*:channel/*:title'
+      xp = '//channel/title'
 
       %w{working.rss broken.rss}.each do |path|
         File.open(File.join(fixture_path(path))) do |file|
Index: test/rexml/test_jaxen.rb
===================================================================
--- test/rexml/test_jaxen.rb	(revision 63277)
+++ test/rexml/test_jaxen.rb	(revision 63278)
@@ -84,7 +84,7 @@ module REXMLTests https://github.com/ruby/ruby/blob/trunk/test/rexml/test_jaxen.rb#L84
     def process_value_of(context, variables, namespaces, value_of)
       expected = value_of.text
       xpath = value_of.attributes["select"]
-      matched = XPath.match(context, xpath, namespaces, variables)
+      matched = XPath.match(context, xpath, namespaces, variables, strict: true)
 
       message = user_message(context, xpath, matched)
       assert_equal(expected || "",
@@ -95,7 +95,7 @@ module REXMLTests https://github.com/ruby/ruby/blob/trunk/test/rexml/test_jaxen.rb#L95
     # processes a tests/document/context/test node ( where @exception is false or doesn't exist )
     def process_nominal_test(context, variables, namespaces, test)
       xpath = test.attributes["select"]
-      matched = XPath.match(context, xpath, namespaces, variables)
+      matched = XPath.match(context, xpath, namespaces, variables, strict: true)
       # might be a test with no count attribute, but nested valueOf elements
       expected = test.attributes["count"]
       if expected
@@ -113,7 +113,7 @@ module REXMLTests https://github.com/ruby/ruby/blob/trunk/test/rexml/test_jaxen.rb#L113
     def process_exceptional_test(context, variables, namespaces, test)
       xpath = test.attributes["select"]
       assert_raise(REXML::ParseException) do
-        XPath.match(context, xpath, namespaces, variables)
+        XPath.match(context, xpath, namespaces, variables, strict: true)
       end
     end
 
Index: test/rss/test_dublincore.rb
===================================================================
--- test/rss/test_dublincore.rb	(revision 63277)
+++ test/rss/test_dublincore.rb	(revision 63278)
@@ -103,8 +103,6 @@ EOR https://github.com/ruby/ruby/blob/trunk/test/rss/test_dublincore.rb#L103
     end
 
     def test_to_s
-      skip # FIXME
-
       assert_dc_to_s(@rss10_source, @rss10_parents, false)
       assert_dc_to_s(@rss10_source, @rss10_parents, true)
 
Index: test/rss/test_1.0.rb
===================================================================
--- test/rss/test_1.0.rb	(revision 63277)
+++ test/rss/test_1.0.rb	(revision 63278)
@@ -54,8 +54,6 @@ module RSS https://github.com/ruby/ruby/blob/trunk/test/rss/test_1.0.rb#L54
     end
 
     def test_channel
-      skip # FIXME
-
       about = "http://hoge.com"
       resource = "http://hoge.com/hoge.png"
 
@@ -207,8 +205,6 @@ EOR https://github.com/ruby/ruby/blob/trunk/test/rss/test_1.0.rb#L205
     end
 
     def test_image
-      skip # FIXME
-
       about = "http://hoge.com"
       h = {
         'title' => "fugafuga",
@@ -234,8 +230,6 @@ EOR https://github.com/ruby/ruby/blob/trunk/test/rss/test_1.0.rb#L230
     end
 
     def test_item
-      skip # FIXME
-
       about = "http://hoge.com"
       h = {
         'title' => "fugafuga",
@@ -261,8 +255,6 @@ EOR https://github.com/ruby/ruby/blob/trunk/test/rss/test_1.0.rb#L255
     end
 
     def test_textinput
-      skip # FIXME
-
       about = "http://hoge.com"
       h = {
         'title' => "fugafuga",
Index: lib/rexml/xpath_parser.rb
===================================================================
--- lib/rexml/xpath_parser.rb	(revision 63277)
+++ lib/rexml/xpath_parser.rb	(revision 63278)
@@ -47,11 +47,12 @@ module REXML https://github.com/ruby/ruby/blob/trunk/lib/rexml/xpath_parser.rb#L47
     include XMLTokens
     LITERAL    = /^'([^']*)'|^"([^"]*)"/u
 
-    def initialize( )
+    def initialize(strict: false)
       @parser = REXML::Parsers::XPathParser.new
       @namespaces = nil
       @variables = {}
       @nest = 0
+      @strict = strict
     end
 
     def namespaces=( namespaces={} )
@@ -139,7 +140,9 @@ module REXML https://github.com/ruby/ruby/blob/trunk/lib/rexml/xpath_parser.rb#L140
     end
 
     private
-
+    def strict?
+      @strict
+    end
 
     # Returns a String namespace for a node, given a prefix
     # The rules are:
@@ -474,7 +477,13 @@ module REXML https://github.com/ruby/ruby/blob/trunk/lib/rexml/xpath_parser.rb#L477
               if prefix.nil?
                 raw_node.name == name
               elsif prefix.empty?
-                raw_node.name == name and raw_node.namespace == ""
+                if strict?
+                  raw_node.name == name and raw_node.namespace == ""
+                else
+                  # FIXME: This DOUBLES the time XPath searches take
+                  ns = get_namespace(raw_node, prefix)
+                  raw_node.name == name and raw_node.namespace == ns
+                end
               else
                 # FIXME: This DOUBLES the time XPath searches take
                 ns = get_namespace(raw_node, prefix)
Index: lib/rexml/xpath.rb
===================================================================
--- lib/rexml/xpath.rb	(revision 63277)
+++ lib/rexml/xpath.rb	(revision 63278)
@@ -28,10 +28,10 @@ module REXML https://github.com/ruby/ruby/blob/trunk/lib/rexml/xpath.rb#L28
     #  XPath.first( doc, "//b"} )
     #  XPath.first( node, "a/x:b", { "x"=>"http://doofus" } )
     #  XPath.first( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"})
-    def XPath::first element, path=nil, namespaces=nil, variables={}
+    def XPath::first(element, path=nil, namespaces=nil, variables={}, options={})
       raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
       raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
-      parser = XPathParser.new
+      parser = XPathParser.new(**options)
       parser.namespaces = namespaces
       parser.variables = variables
       path = "*" unless path
@@ -57,10 +57,10 @@ module REXML https://github.com/ruby/ruby/blob/trunk/lib/rexml/xpath.rb#L57
     #  XPath.each( node, 'ancestor::x' ) { |el| ... }
     #  XPath.each( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"}) \
     #    {|el| ... }
-    def XPath::each element, path=nil, namespaces=nil, variables={}, &block
+    def XPath::each(element, path=nil, namespaces=nil, variables={}, options={}, &block)
       raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
       raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
-      parser = XPathParser.new
+      parser = XPathParser.new(**options)
       parser.namespaces = namespaces
       parser.variables = variables
       path = "*" unless path
@@ -69,8 +69,8 @@ module REXML https://github.com/ruby/ruby/blob/trunk/lib/rexml/xpath.rb#L69
     end
 
     # Returns an array of nodes matching a given XPath.
-    def XPath::match element, path=nil, namespaces=nil, variables={}
-      parser = XPathParser.new
+    def XPath::match(element, path=nil, namespaces=nil, variables={}, options={})
+      parser = XPathParser.new(**options)
       parser.namespaces = namespaces
       parser.variables = variables
       path = "*" unless path
Index: spec/ruby/library/rexml/element/prefixes_spec.rb
===================================================================
--- spec/ruby/library/rexml/element/prefixes_spec.rb	(revision 63277)
+++ spec/ruby/library/rexml/element/prefixes_spec.rb	(revision 63278)
@@ -7,7 +7,6 @@ describe "REXML::Element#prefixes" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/library/rexml/element/prefixes_spec.rb#L7
     @elem = doc.elements["//c"]
   end
 
-=begin
   it "returns an array of the prefixes of the namespaces" do
     @elem.prefixes.should == ["y", "z"]
   end
@@ -15,7 +14,6 @@ describe "REXML::Element#prefixes" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/library/rexml/element/prefixes_spec.rb#L14
   it "does not include the default namespace" do
     @elem.prefixes.include?("xmlns").should == false
   end
-=end
 
   it "returns an empty array if no namespace was defined" do
     doc = REXML::Document.new "<root><something/></root>"
Index: spec/ruby/library/rexml/element/namespaces_spec.rb
===================================================================
--- spec/ruby/library/rexml/element/namespaces_spec.rb	(revision 63277)
+++ spec/ruby/library/rexml/element/namespaces_spec.rb	(revision 63278)
@@ -7,7 +7,6 @@ describe "REXML::Element#namespaces" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/library/rexml/element/namespaces_spec.rb#L7
     @elem = doc.elements["//c"]
   end
 
-=begin
   it "returns a hash of the namespaces" do
     ns = {"y"=>"2", "z"=>"3", "xmlns"=>"1"}
     @elem.namespaces.keys.sort.should == ns.keys.sort
@@ -29,5 +28,4 @@ describe "REXML::Element#namespaces" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/library/rexml/element/namespaces_spec.rb#L28
     values = ["2", "3", "1"]
     @elem.namespaces.values.sort.should == values.sort
   end
-=end
 end
Index: spec/ruby/library/rexml/element/namespace_spec.rb
===================================================================
--- spec/ruby/library/rexml/element/namespace_spec.rb	(revision 63277)
+++ spec/ruby/library/rexml/element/namespace_spec.rb	(revision 63278)
@@ -1,8 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/spec/ruby/library/rexml/element/namespace_spec.rb#L1
 require 'rexml/document'
 require_relative '../../../spec_helper'
 
-=begin
-# FIXME
 describe "REXML::Element#namespace" do
   before :each do
     @doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
@@ -27,4 +25,3 @@ describe "REXML::Element#namespace" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/library/rexml/element/namespace_spec.rb#L25
     @elem.namespace("z").should be_nil
   end
 end
-=end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]