Fix entity encoding of attribute values

This ensures that single and double quotes are also encoded, previously
they would be left as is.

Fixes #113
This commit is contained in:
Yorick Peterse 2015-06-16 22:47:10 +02:00
parent e0837fd44e
commit 074b53c18c
4 changed files with 60 additions and 4 deletions

View File

@ -101,7 +101,11 @@ module Oga
full_name = name
end
enc_value = value ? Entities.encode(value) : nil
if value
enc_value = Entities.encode_attribute(value)
else
enc_value = nil
end
%Q(#{full_name}="#{enc_value}")
end

View File

@ -32,6 +32,20 @@ module Oga
'<' => '&lt;',
}
##
# Hash containing characters and the corresponding XML entities to use
# when encoding XML/HTML attribute values.
#
# @return [Hash]
#
ENCODE_ATTRIBUTE_MAPPING = {
'&' => '&amp;',
'>' => '&gt;',
'<' => '&lt;',
"'" => '&apos;',
'"' => '&quot;'
}
##
# @return [String]
#
@ -56,6 +70,12 @@ module Oga
#
ENCODE_REGEXP = Regexp.new(ENCODE_MAPPING.keys.join('|'))
##
# @return [Regexp]
#
ENCODE_ATTRIBUTE_REGEXP =
Regexp.new(ENCODE_ATTRIBUTE_MAPPING.keys.join('|'))
##
# Decodes XML entities.
#
@ -87,6 +107,16 @@ module Oga
def self.encode(input, mapping = ENCODE_MAPPING)
input.gsub(ENCODE_REGEXP, mapping)
end
##
# Encodes special characters in an XML attribute value.
#
# @param [String] input
# @return [String]
#
def self.encode_attribute(input)
input.gsub(ENCODE_ATTRIBUTE_REGEXP, ENCODE_ATTRIBUTE_MAPPING)
end
end # Entities
end # XML
end # Oga

View File

@ -139,10 +139,10 @@ describe Oga::XML::Attribute do
attr.to_xml.should == 'xmlns:class=""'
end
it 'converts special characters to XML entities' do
attr = described_class.new(:name => 'href', :value => '&<>')
it 'decodes XML entities' do
attr = described_class.new(:name => 'href', :value => %q{&<>'"})
attr.to_xml.should == 'href="&amp;&lt;&gt;"'
attr.to_xml.should == 'href="&amp;&lt;&gt;&apos;&quot;"'
end
end

View File

@ -104,4 +104,26 @@ describe Oga::XML::Entities do
described_class.encode('&lt;').should == '&amp;lt;'
end
end
describe 'encode_attribute' do
it 'encodes & as &amp;' do
described_class.encode_attribute('&').should == '&amp;'
end
it 'encodes > as &gt;' do
described_class.encode_attribute('>').should == '&gt;'
end
it 'encodes < as &gt;' do
described_class.encode_attribute('<').should == '&lt;'
end
it 'encodes a single quote as &apos;' do
described_class.encode_attribute("'").should == '&apos;'
end
it 'encodes a double quote as &quot;' do
described_class.encode_attribute('"').should == '&quot;'
end
end
end