Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Literal#typed namespaces option now is {prefix => href} rather than {…

…prefix => Namespace}.

No longer pass vocabularies, prefixes or terms. Only namespaces derived via xmlns are passed to Literal#typed.
  • Loading branch information...
commit 14f8701e7f047bda5e1bd8e77db33b0ac5206a08 1 parent 470b490
@gkellogg authored
Showing with 41 additions and 84 deletions.
  1. +16 −54 lib/rdf_context/literal.rb
  2. +25 −30 lib/rdf_context/rdfaparser.rb
View
70 lib/rdf_context/literal.rb
@@ -245,14 +245,15 @@ def xml_args(content, lang)
# @param [Object] contents
# @option options [Hash] :namespaces ({}) Use :__default__ or "" to declare default namespace
# @option options [String] :language (nil)
- # @option options [Array<URIRef>] :profiles ([]) Profiles to add to elements
- # @option options [Hash] :prefixes (nil) Prefixes to add to elements
- # @option options [String] :default_vocabulary (nil) Default vocabulary to add to elements
def encode_contents(contents, options)
#puts "encode_contents: '#{contents}'"
+ ns_hash = {}
+ (options[:namespaces] || {}).each_pair do |pfx, href|
+ href = href.uri.to_s if href.is_a?(Namespace)
+ ns_hash[pfx.to_s.empty? ? "xmlns" : "xmlns:#{pfx}"] = href.to_s
+ end
if contents.is_a?(String)
- ns_hash = options[:namespaces].values.inject({}) {|h, ns| h.merge(ns.xmlns_hash)}
ns_strs = []
ns_hash.each_pair {|a, u| ns_strs << "#{a}=\"#{u}\""}
@@ -266,59 +267,20 @@ def encode_contents(contents, options)
c = Nokogiri::XML.parse(c.copy(true).to_s) if c.is_a?(LibXML::XML::Node)
end
if c.is_a?(Nokogiri::XML::Element)
+ # For real XML C14N recursive processing is required. However, as a first step,
+ # we can just be sure that top-level attributes and namespace declarations are properly
+ # and relatively ordered
+ # From http://www.w3.org/TR/2000/WD-xml-c14n-20001011#Example-SETags
+ # * Relative order of namespace and attribute axes
+ # * Lexicographic ordering of namespace and attribute axes
c = Nokogiri::XML.parse(c.dup.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS)).root
- # Gather namespaces from self and decendant nodes
- #
- # prefix mappings
- # Look for @xmlns and @prefix mappings. Add any other mappings from options[:prefixes]
- # that aren't already defined on this node
- defined_mappings = {}
- prefix_mappings = {}
-
- c.traverse do |n|
- ns = n.namespace
- next unless ns
- prefix = ns.prefix ? "xmlns:#{ns.prefix}" : "xmlns"
- defined_mappings[ns.prefix.to_s] = ns.href.to_s
- c[prefix] = ns.href unless c.namespaces[prefix]
- end
-
- mappings = c["prefix"].to_s.split(/\s+/)
- while mappings.length > 0 do
- prefix, uri = mappings.shift.downcase, mappings.shift
- #puts "uri_mappings prefix #{prefix} <#{uri}>"
- next unless prefix.match(/:$/)
- prefix.chop!
-
- # A Conforming RDFa Processor must ignore any definition of a mapping for the '_' prefix.
- next if prefix == "_"
-
- defined_mappings[prefix] = uri
- prefix_mappings[prefix] = uri
- end
- # Add prefixes, being careful to honor mappings defined on the element
- if options[:prefixes]
- options[:prefixes].each_pair do |p, ns|
- prefix_mappings[p] = ns.uri unless defined_mappings.has_key?(p)
- end
- if prefix_mappings.length
- c["prefix"] = prefix_mappings.keys.sort.map {|p| "#{p}: #{prefix_mappings[p]}"}.join(" ")
- end
- end
-
- # Add profiles, being careful to honor profiles defined on the element
- if options[:profiles].is_a?(Array) && options[:profiles].length > 0
- profiles = c["profile"].to_s.split(" ")
- profiles += options[:profiles]
- c["profile"] = profiles.join(" ")
- end
-
- # Add default vocabulary, being careful to honor any defined on the element
- if options[:default_vocabulary] && !c["vocab"]
- c["vocab"] = options[:default_vocabulary].to_s
+ # Apply defined namespaces
+ ns_hash.each_pair do |prefix, href|
+ c[prefix] = href unless c.namespaces[prefix]
end
+ # Add language
if options[:language] && c["lang"].to_s.empty?
c["xml:lang"] = options[:language]
end
@@ -460,7 +422,7 @@ def self.infer_encoding_for(object)
end
end
- class << self
+ class << self
protected :new
end
View
55 lib/rdf_context/rdfaparser.rb
@@ -67,14 +67,15 @@ class EvaluationContext # :nodoc:
#
# @return URIRef
attr :parent_object, true
- # A list of current, in-scope profiles.
- #
- # @return [Array<URIRef>]
- attr :profiles, true
# A list of current, in-scope URI mappings.
#
# @return [Hash{String => Namespace}]
attr :uri_mappings, true
+ # A list of current, in-scope Namespaces. This is the subset of uri_mappings
+ # which are defined using xmlns.
+ #
+ # @return [Hash{String => Namespace}]
+ attr :namespaces, true
# A list of incomplete triples.
#
# A triple can be incomplete when no object resource
@@ -114,8 +115,8 @@ def initialize(base, host_defaults)
@base = base
@parent_subject = @base
@parent_object = nil
- @profiles = []
@uri_mappings = host_defaults.fetch(:uri_mappings, {})
+ @namespaces = {}
@incomplete_triples = []
@language = nil
@term_mappings = host_defaults.fetch(:term_mappings, {})
@@ -129,7 +130,7 @@ def initialize_copy(from)
# clone the evaluation context correctly
@uri_mappings = from.uri_mappings.clone
@incomplete_triples = from.incomplete_triples.clone
- @profiles = from.profiles.clone
+ @namespaces = from.namespaces.clone
end
def inspect
@@ -137,7 +138,6 @@ def inspect
v << "uri_mappings[#{uri_mappings.keys.length}]"
v << "incomplete_triples[#{incomplete_triples.length}]"
v << "term_mappings[#{term_mappings.keys.length}]"
- v << "profiles[#{profiles.length}]"
v.join(",")
end
end
@@ -352,7 +352,7 @@ def process_profile(element, profiles)
end
# Extract the XMLNS mappings from an element
- def extract_mappings(element, uri_mappings)
+ def extract_mappings(element, uri_mappings, namespaces)
# look for xmlns
# (note, this may be dependent on @host_language)
# Regardless of how the mapping is declared, the value to be mapped must be converted to lower case,
@@ -367,8 +367,12 @@ def extract_mappings(element, uri_mappings)
# Downcase prefix for RDFa 1.1
pfx_lc = (@version == :rdfa_1_0 || ns.prefix.nil?) ? ns.prefix : ns.prefix.to_s.downcase
if ns.prefix
- uri_mappings[pfx_lc] = @graph.bind(Namespace.new(ns.href, ns.prefix.to_s))
+ namespace = Namespace.new(ns.href, ns.prefix.to_s)
+ uri_mappings[pfx_lc] = @graph.bind(namespace)
+ namespaces[pfx_lc] ||= ns.href.to_s
add_debug(element, "extract_mappings: xmlns:#{ns.prefix} => <#{ns.href}>")
+ else
+ namespaces[""] ||= ns.href.to_s
end
rescue RdfException => e
@@ -410,6 +414,7 @@ def traverse(element, evaluation_context)
new_subject = nil
current_object_resource = nil
uri_mappings = evaluation_context.uri_mappings.clone
+ namespaces = evaluation_context.namespaces.clone
incomplete_triples = []
language = evaluation_context.language
term_mappings = evaluation_context.term_mappings.clone
@@ -456,10 +461,7 @@ def traverse(element, evaluation_context)
return
end
end
-
- # Add on proviles from parent contexts to update new context
- profiles += evaluation_context.profiles.clone
-
+
# Default vocabulary [7.5 Step 3]
# Next the current element is examined for any change to the default vocabulary via @vocab.
# If @vocab is present and contains a value, its value updates the local default vocabulary.
@@ -478,7 +480,7 @@ def traverse(element, evaluation_context)
# Local term mappings [7.5 Steps 4]
# Next, the current element is then examined for URI mapping s and these are added to the local list of URI mappings.
# Note that a URI mapping will simply overwrite any current mapping in the list that has the same name
- extract_mappings(element, uri_mappings)
+ extract_mappings(element, uri_mappings, namespaces)
# Language information [7.5 Step 5]
# From HTML5 [3.2.3.3]
@@ -663,18 +665,12 @@ def traverse(element, evaluation_context)
add_debug(element, "[Step 11(1.1)] XML Literal: #{element.inner_html}")
# In order to maintain maximum portability of this literal, any children of the current node that are
- # elements must have the current in scope profiles, default vocabulary, prefix mappings, and XML
- # namespace declarations (if any) declared on the serialized element using their respective attributes.
- # Since the child element node could also declare new prefix mappings or XML namespaces, the RDFa
- # Processor must be careful to merge these together when generating the serialized element definition.
- # For avoidance of doubt, any re-declarations on the child node must take precedence over declarations
- # that were active on the current node.
- Literal.typed(element.children, XML_LITERAL,
- :language => language,
- :namespaces => uri_mappings,
- :profiles => profiles,
- :prefixes => uri_mappings,
- :default_vocabulary => default_vocabulary)
+ # elements must have the current in scope XML namespace declarations (if any) declared on the
+ # serialized element using their respective attributes. Since the child element node could also
+ # declare new XML namespaces, the RDFa Processor must be careful to merge these together when
+ # generating the serialized element definition. For avoidance of doubt, any re-declarations on the
+ # child node must take precedence over declarations that were active on the current node.
+ Literal.typed(element.children, XML_LITERAL, :language => language, :namespaces => namespaces)
else
# plain literal
add_debug(element, "[Step 11(1.1)] plain literal")
@@ -689,7 +685,7 @@ def traverse(element, evaluation_context)
# XML Literal
add_debug(element, "[Step 11 (1.0)] XML Literal: #{element.inner_html}")
recurse = false
- Literal.typed(element.children, XML_LITERAL, :language => language, :namespaces => uri_mappings)
+ Literal.typed(element.children, XML_LITERAL, :language => language, :namespaces => namespaces)
end
end
@@ -718,16 +714,15 @@ def traverse(element, evaluation_context)
uri_mappings == evaluation_context.uri_mappings &&
term_mappings == evaluation_context.term_mappings &&
default_vocabulary == evaluation_context.default_vocabulary &&
- profiles == evaluation_context.profiles
new_ec = evaluation_context
add_debug(element, "[Step 13] skip: reused ec")
else
new_ec = evaluation_context.clone
new_ec.language = language
new_ec.uri_mappings = uri_mappings
+ new_ec.namespaces = namespaces
new_ec.term_mappings = term_mappings
new_ec.default_vocabulary = default_vocabulary
- new_ec.profiles = profiles
add_debug(element, "[Step 13] skip: cloned ec")
end
else
@@ -736,11 +731,11 @@ def traverse(element, evaluation_context)
new_ec.parent_subject = new_subject || evaluation_context.parent_subject
new_ec.parent_object = current_object_resource || new_subject || evaluation_context.parent_subject
new_ec.uri_mappings = uri_mappings
+ new_ec.namespaces = namespaces
new_ec.incomplete_triples = incomplete_triples
new_ec.language = language
new_ec.term_mappings = term_mappings
new_ec.default_vocabulary = default_vocabulary
- new_ec.profiles = profiles
add_debug(element, "[Step 13] new ec")
end
Please sign in to comment.
Something went wrong with that request. Please try again.