mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[ruby/rexml] Fix attribute's default namespace behavior
NOTE: It's a backward incompatible change. If we have any serious problems with this change, we may revert this change. The XML namespace specification says the default namespace doesn't apply to attribute names but it does in REXML without this change: https://www.w3.org/TR/xml-names/#uniqAttrs > the default namespace does not apply to attribute names REXML reports a parse error for the following XML that is described as a valid XML in the XML nsmaspace specification without this change: <!-- http://www.w3.org is bound to n1 and is the default --> <x xmlns:n1="http://www.w3.org" xmlns="http://www.w3.org" > <good a="1" b="2" /> <good a="1" n1:a="2" /> </x> If attribute doesn't have prefix, the attribute should return "" for both #prefix and #namespace. https://github.com/ruby/rexml/commit/9e4fd552bc
This commit is contained in:
parent
9b36f0a787
commit
0f18bc7fca
4 changed files with 63 additions and 22 deletions
|
@ -67,15 +67,11 @@ module REXML
|
|||
# e.add_attribute( "nsa:a", "aval" )
|
||||
# e.add_attribute( "b", "bval" )
|
||||
# e.attributes.get_attribute( "a" ).prefix # -> "nsa"
|
||||
# e.attributes.get_attribute( "b" ).prefix # -> "elns"
|
||||
# e.attributes.get_attribute( "b" ).prefix # -> ""
|
||||
# a = Attribute.new( "x", "y" )
|
||||
# a.prefix # -> ""
|
||||
def prefix
|
||||
pf = super
|
||||
if pf == ""
|
||||
pf = @element.prefix if @element
|
||||
end
|
||||
pf
|
||||
super
|
||||
end
|
||||
|
||||
# Returns the namespace URL, if defined, or nil otherwise
|
||||
|
@ -87,9 +83,8 @@ module REXML
|
|||
# e.attribute("ns:a").namespace # => "http://url"
|
||||
# e.attribute("nsx:a").namespace # => nil
|
||||
#
|
||||
# TODO: This method should always return nil for no namespace
|
||||
# attribute. Because the default namespace doesn't apply to
|
||||
# attribute name.
|
||||
# This method always returns "" for no namespace attribute. Because
|
||||
# the default namespace doesn't apply to attribute names.
|
||||
#
|
||||
# From https://www.w3.org/TR/xml-names/#uniqAttrs
|
||||
#
|
||||
|
@ -99,10 +94,14 @@ module REXML
|
|||
# e.add_namespace("", "http://example.com/")
|
||||
# e.namespace # => "http://example.com/"
|
||||
# e.add_attribute("a", "b")
|
||||
# e.attribute("a").namespace # => nil
|
||||
# e.attribute("a").namespace # => ""
|
||||
def namespace arg=nil
|
||||
arg = prefix if arg.nil?
|
||||
@element.namespace arg
|
||||
if arg == ""
|
||||
""
|
||||
else
|
||||
@element.namespace(arg)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns true if other is an Attribute and has the same name and value,
|
||||
|
|
|
@ -1133,8 +1133,8 @@ module REXML
|
|||
elsif old_attr.prefix != value.prefix
|
||||
# Check for conflicting namespaces
|
||||
if value.prefix != "xmlns" and old_attr.prefix != "xmlns"
|
||||
old_namespace = @element.namespace(old_attr.prefix)
|
||||
new_namespace = @element.namespace(value.prefix)
|
||||
old_namespace = old_attr.namespace
|
||||
new_namespace = value.namespace
|
||||
if old_namespace == new_namespace
|
||||
raise ParseException.new(
|
||||
"Namespace conflict in adding attribute \"#{value.name}\": "+
|
||||
|
|
|
@ -493,17 +493,11 @@ module REXML
|
|||
if prefix.nil?
|
||||
raw_node.name == name
|
||||
elsif prefix.empty?
|
||||
# FIXME: This DOUBLES the time XPath searches take
|
||||
raw_node.name == name and
|
||||
raw_node.namespace == raw_node.element.namespace
|
||||
raw_node.name == name and raw_node.namespace == ""
|
||||
else
|
||||
# FIXME: This DOUBLES the time XPath searches take
|
||||
ns = get_namespace(raw_node.element, prefix)
|
||||
if ns.empty?
|
||||
raw_node.name == name and raw_node.prefix.empty?
|
||||
else
|
||||
raw_node.name == name and raw_node.namespace == ns
|
||||
end
|
||||
raw_node.name == name and raw_node.namespace == ns
|
||||
end
|
||||
else
|
||||
false
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# coding: binary
|
||||
# -*- coding: utf-8 -*-
|
||||
# frozen_string_literal: false
|
||||
|
||||
require_relative "rexml_test_utils"
|
||||
|
@ -116,6 +116,54 @@ module REXMLTests
|
|||
name4='test4'/>).join(' '), e.to_s
|
||||
end
|
||||
|
||||
def test_attribute_namespace_conflict
|
||||
# https://www.w3.org/TR/xml-names/#uniqAttrs
|
||||
message = <<-MESSAGE
|
||||
Duplicate attribute "a"
|
||||
Line: 4
|
||||
Position: 140
|
||||
Last 80 unconsumed characters:
|
||||
MESSAGE
|
||||
assert_raise_with_message(REXML::ParseException, message) do
|
||||
Document.new(<<-XML)
|
||||
<!-- http://www.w3.org is bound to n1 and n2 -->
|
||||
<x xmlns:n1="http://www.w3.org"
|
||||
xmlns:n2="http://www.w3.org" >
|
||||
<bad a="1" a="2" />
|
||||
<bad n1:a="1" n2:a="2" />
|
||||
</x>
|
||||
XML
|
||||
end
|
||||
end
|
||||
|
||||
def test_attribute_default_namespace
|
||||
# https://www.w3.org/TR/xml-names/#uniqAttrs
|
||||
document = Document.new(<<-XML)
|
||||
<!-- http://www.w3.org is bound to n1 and is the default -->
|
||||
<x xmlns:n1="http://www.w3.org"
|
||||
xmlns="http://www.w3.org" >
|
||||
<good a="1" b="2" />
|
||||
<good a="1" n1:a="2" />
|
||||
</x>
|
||||
XML
|
||||
attributes = document.root.elements.collect do |element|
|
||||
element.attributes.each_attribute.collect do |attribute|
|
||||
[attribute.prefix, attribute.namespace, attribute.name]
|
||||
end
|
||||
end
|
||||
assert_equal([
|
||||
[
|
||||
["", "", "a"],
|
||||
["", "", "b"],
|
||||
],
|
||||
[
|
||||
["", "", "a"],
|
||||
["n1", "http://www.w3.org", "a"],
|
||||
],
|
||||
],
|
||||
attributes)
|
||||
end
|
||||
|
||||
def test_cdata
|
||||
test = "The quick brown fox jumped
|
||||
& < & < \" '
|
||||
|
|
Loading…
Add table
Reference in a new issue