Permalink
Browse files

Added vocabulary expansion, controlled using :vocab_expansion option.

  • Loading branch information...
1 parent 29b72a0 commit 5ed66455312beb78f9ac80cd672b061ffbb03c29 @gkellogg gkellogg committed Sep 20, 2012
Showing with 578 additions and 19 deletions.
  1. +6 −3 lib/rdf/microdata.rb
  2. +159 −0 lib/rdf/microdata/expansion.rb
  3. +60 −16 lib/rdf/microdata/reader.rb
  4. +253 −0 spec/expansion_spec.rb
  5. +88 −0 spec/reader_spec.rb
  6. +12 −0 spec/test-files/test-registry.json
View
9 lib/rdf/microdata.rb
@@ -20,11 +20,14 @@ module RDF
#
# @author [Gregg Kellogg](http://greggkellogg.net/)
module Microdata
+ USES_VOCAB = RDF::URI("http://www.w3.org/ns/rdfa#usesVocabulary")
+
require 'rdf/microdata/format'
require 'rdf/microdata/vocab'
- autoload :Profile, 'rdf/microdata/profile'
- autoload :Reader, 'rdf/microdata/reader'
- autoload :VERSION, 'rdf/microdata/version'
+ autoload :Expansion, 'rdf/microdata/expansion'
+ autoload :Profile, 'rdf/microdata/profile'
+ autoload :Reader, 'rdf/microdata/reader'
+ autoload :VERSION, 'rdf/microdata/version'
def self.debug?; @debug; end
def self.debug=(value); @debug = value; end
View
159 lib/rdf/microdata/expansion.rb
@@ -0,0 +1,159 @@
+module RDF::Microdata
+ ##
+ # The Expansion module performs a subset of OWL entailment rules on the base class,
+ # which implementes RDF::Readable.
+ module Expansion
+ ##
+ # Perform vocabulary expansion on the resulting default graph.
+ #
+ # Vocabulary expansion relies on a sub-set of OWL [OWL2-PROFILES] entailment to add triples to the default graph based on rules and property/class relationships described in referenced vocabularies.
+ #
+ # For all objects that are the target of an rdfa:usesVocabulary property, load the IRI into a repository.
+ #
+ # Subsequently, perform OWL expansion using rules prp-spo1, prp-eqp1, and prp-eqp2 placing resulting triples into the default graph. Iterate on this step until no more triples are added.
+ #
+ # @example
+ # scm-spo
+ # {pq rdfs:subPropertyOf pw . pw rdfs:subPropertyOf p3}
+ # => {p1 rdfs:subPropertyOf p3}
+ #
+ # rdprp-spo1fs7
+ # {p1 rdfs:subPropertyOf p2 . x p1 y} => {x p2 y}
+ #
+ # @return [RDF::Graph]
+ # @see [OWL2 PROFILES](http://www.w3.org/TR/2009/REC-owl2-profiles-20091027/#Reasoning_in_OWL_2_RL_and_RDF_Graphs_using_Rules)
+ def expand
+ repo = RDF::Repository.new
+ repo << self # Add default graph
+
+ count = repo.count
+ add_debug("expand") {"Loaded #{repo.size} triples into default graph"}
+
+ repo = owl_entailment(repo)
+
+ # Return graph with default context
+ graph = RDF::Graph.new
+ repo.statements.each {|st| graph << st if st.context.nil?}
+ graph
+ end
+
+ def rule(name, &block)
+ Rule.new(name, block)
+ end
+
+ ##
+ # An entailment rule
+ #
+ # Takes a list of antecedent patterns used to find solutions against a queryable
+ # object. Yields each consequent with bindings from the solution
+ class Rule
+ # @attr [Array<RDF::Query::Pattern>]
+ attr_reader :antecedents
+
+ # @attr [Array<RDF::Query::Pattern>]
+ attr_reader :consequents
+
+ # @attr [String] name
+ attr_reader :name
+
+ ##
+ # @example
+ # r = Rule.new("scm-spo") do
+ # antecedent :p1, RDF::RDFS.subPropertyOf, :p2
+ # antecedent :p2, RDF::RDFS.subPropertyOf, :p3
+ # consequent :p1, RDF::RDFS.subPropertyOf, :p3, "t-box"
+ # end
+ #
+ # r.execute(queryable) {|statement| puts statement.inspect}
+ #
+ # @param [String] name
+ def initialize(name, &block)
+ @antecedents = []
+ @consequents = []
+ @name = name
+
+ if block_given?
+ case block.arity
+ when 1 then block.call(self)
+ else instance_eval(&block)
+ end
+ end
+ end
+
+ def antecedent(subject, prediate, object, context = nil)
+ antecedents << RDF::Query::Pattern.new(subject, prediate, object, :context => context)
+ end
+
+ def consequent(subject, prediate, object, context = nil)
+ consequents << RDF::Query::Pattern.new(subject, prediate, object, :context => context)
+ end
+
+ ##
+ # Execute the rule against queryable, yielding each consequent with bindings
+ #
+ # @param [RDF::Queryable] queryable
+ # @yield [statement]
+ # @yieldparam [RDF::Statement] statement
+ def execute(queryable)
+ RDF::Query.new(antecedents).execute(queryable).each do |solution|
+ nodes = {}
+ consequents.each do |consequent|
+ terms = {}
+ [:subject, :predicate, :object, :context].each do |r|
+ terms[r] = case o = consequent.send(r)
+ when RDF::Node then nodes[o] ||= RDF::Node.new
+ when RDF::Query::Variable then solution[o]
+ else o
+ end
+ end
+
+ yield RDF::Statement.from(terms)
+ end
+ end
+ end
+ end
+
+ private
+
+ RULES = [
+ Rule.new("prp-spo1") do
+ antecedent :p1, RDF::RDFS.subPropertyOf, :p2
+ antecedent :x, :p1, :y
+ consequent :x, :p2, :y
+ end,
+ Rule.new("prp-eqp1") do
+ antecedent :p1, RDF::OWL.equivalentProperty, :p2
+ antecedent :x, :p1, :y
+ consequent :x, :p2, :y
+ end,
+ Rule.new("prp-eqp2") do
+ antecedent :p1, RDF::OWL.equivalentProperty, :p2
+ antecedent :x, :p2, :y
+ consequent :x, :p1, :y
+ end,
+ ]
+
+ ##
+ # Perform OWL entailment rules on enumerable
+ # @param [RDF::Enumerable] repo
+ # @return [RDF::Enumerable]
+ def owl_entailment(repo)
+ old_count = 0
+
+ while old_count < (count = repo.count)
+ add_debug("entailment", "old: #{old_count} count: #{count}")
+ old_count = count
+
+ RULES.each do |rule|
+ rule.execute(repo) do |statement|
+ add_debug("entailment(#{rule.name})") {statement.inspect}
+ repo << statement
+ end
+ end
+ end
+
+ add_debug("entailment", "final count: #{count}")
+ repo
+ end
+ end
+end
View
76 lib/rdf/microdata/reader.rb
@@ -17,9 +17,9 @@ module RDF::Microdata
# @author [Gregg Kellogg](http://greggkellogg.net/)
class Reader < RDF::Reader
format Format
+ include Expansion
URL_PROPERTY_ELEMENTS = %w(a area audio embed iframe img link object source track video)
DEFAULT_REGISTRY = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "etc", "registry.json"))
- USES_VOCAB = RDF::URI("http://www.w3.org/ns/rdfa#usesVocabulary")
class CrawlFailure < StandardError #:nodoc:
end
@@ -117,29 +117,26 @@ def predicateURI(name, ec)
n = frag_escape(name)
if ec[:current_type].nil?
# 2) If current type from context is null, there can be no current vocabulary.
- # Return the URI reference that is the document base with its fragment set to
- # the fragment-escaped value of name
+ # Return the URI reference that is the document base with its fragment set to the fragment-escaped value of name
u = RDF::URI(ec[:document_base].to_s)
u.fragment = frag_escape(name)
u
elsif @scheme == :vocabulary
- # 4) If scheme is vocabulary return the URI reference constructed by appending the fragment escaped value of name
- # to current vocabulary, separated by a U+0023 NUMBER SIGN character (#) unless the current vocabulary ends
- # with either a U+0023 NUMBER SIGN character (#) or SOLIDUS U+002F (/).
+ # 4) If scheme is vocabulary return the URI reference constructed by appending the fragment escaped value of name to current vocabulary, separated by a U+0023 NUMBER SIGN character (#) unless the current vocabulary ends with either a U+0023 NUMBER SIGN character (#) or SOLIDUS U+002F (/).
RDF::URI(@property_base + n)
else # @scheme == :contextual
if ec[:current_name].to_s.index(@property_base) == 0
# 5.2) return the concatenation of s, a U+002E FULL STOP character (.) and the fragment-escaped value of name.
RDF::URI(ec[:current_name] + '.' + n)
else
- # 5.3) return the concatenation of http://www.w3.org/ns/md?type=, the fragment-escaped value of current type,
- # the string &prop=, and the fragment-escaped value of name
- RDF::URI(@property_base + frag_escape(ec[:current_type]) + '&prop=' + n)
+ # 5.3) return the concatenation of http://www.w3.org/ns/md?type=, the fragment-escaped value of current type, the string &prop=, and the fragment-escaped value of name
+ RDF::URI(@property_base +
+ frag_escape(ec[:current_type]) +
+ '&prop=' + n)
end
end
end
-
-
+
##
# Turn a predicateURI into a simple token
# @param [RDF::URI] predicateURI
@@ -159,14 +156,41 @@ def tokenize(predicateURI)
# @return [Boolean]
def as_list(predicateURI)
tok = tokenize(predicateURI)
- if @properties[tok].is_a?(Hash)
+ if @properties[tok].is_a?(Hash) &&
+ @properties[tok].has_key?("multipleValues")
@properties[tok]["multipleValues"].to_sym == :list
else
@multipleValues == :list
end
end
##
+ # Yield a equivalentProperty or subPropertyOf if appropriate
+ # @param [RDF::URI] predicateURI
+ # @yield :statement
+ # @yieldparam [RDF::Statement] statement
+ # @return [Boolean]
+ def expand(predicateURI)
+ tok = tokenize(predicateURI)
+ if @properties[tok].is_a?(Hash)
+ if value = @properties[tok]["equivalentProperty"]
+ [value].flatten.each do |v|
+ yield RDF::Statement.new(predicateURI,
+ RDF::OWL.equivalentProperty,
+ RDF::URI(v))
+ end
+ elsif value = @properties[tok]["subPropertyOf"]
+ [value].flatten.each do |v|
+ yield RDF::Statement.new(predicateURI,
+ RDF::RDFS.subPropertyOf,
+ RDF::URI(v))
+ end
+ end
+ value = @properties[tok]
+ end
+ end
+
+ ##
# Fragment escape a name
def frag_escape(name)
name.to_s.gsub(/["#%<>\[\\\]^{|}]/) {|c| '%' + c.unpack('H2' * c.bytesize).join('%').upcase}
@@ -193,6 +217,8 @@ def frag_escape(name)
# @option options [#to_s] :base_uri (nil)
# the base URI to use when resolving relative URIs
# @option options [#to_s] :registry_uri (DEFAULT_REGISTRY)
+ # @option options [Boolean] :vocab_expansion (true)
+ # whether to perform OWL2 expansion on the resulting graph
# @option options [Array] :debug
# Array to place debug messages
# @return [reader]
@@ -203,6 +229,7 @@ def frag_escape(name)
def initialize(input = $stdin, options = {}, &block)
super do
@debug = options[:debug]
+ @vocab_expansion = options.fetch(:vocab_expansion, true)
@library = case options[:library]
when nil
@@ -228,7 +255,7 @@ def initialize(input = $stdin, options = {}, &block)
errors = doc_errors.reject {|e| e.to_s =~ /Tag (audio|source|track|video|time) invalid/}
raise RDF::ReaderError, "Syntax errors:\n#{errors}" if !errors.empty? && validate?
- add_debug(@doc, "library = #{@library}")
+ add_debug(@doc, "library = #{@library}, expand = #{@vocab_expansion}")
# Load registry
begin
@@ -251,14 +278,22 @@ def initialize(input = $stdin, options = {}, &block)
##
# Iterates the given block for each RDF statement in the input.
#
+ # Reads to graph and performs expansion if required.
+ #
# @yield [statement]
# @yieldparam [RDF::Statement] statement
# @return [void]
def each_statement(&block)
- @callback = block
+ if @vocab_expansion
+ @vocab_expansion = false
+ expand.each_statement(&block)
+ @vocab_expansion = true
+ else
+ @callback = block
- # parse
- parse_whole_document(@doc, base_uri)
+ # parse
+ parse_whole_document(@doc, base_uri)
+ end
end
##
@@ -433,6 +468,15 @@ def generate_triples(item, ec = {})
# 11.1.2) Let predicate be the result of generate predicate URI using context and name. Update context by setting current name to predicate.
predicate = vocab.predicateURI(name, ec_new)
+
+ # (Generate Predicate URI steps 6 and 7)
+ vocab.expand(predicate) do |statement|
+ add_debug(item) {
+ "gentrips(11.1.2): expansion #{statement.inspect}"
+ }
+ @callback.call(statement)
+ end
+
ec_new[:current_name] = predicate
add_debug(item) {"gentrips(11.1.2): predicate=#{predicate}"}
View
253 spec/expansion_spec.rb
@@ -0,0 +1,253 @@
+$:.unshift "."
+require 'spec_helper'
+
+# Class for abstract testing of module
+class ExpansionTester
+ include RDF::Microdata::Expansion
+ include RDF::Enumerable
+
+ attr_reader :about, :information, :repo, :inputDocument, :outputDocument, :options
+ attr :format, true
+
+ def initialize(name)
+ @about = @information = name
+ @repo = RDF::Repository.new
+
+ super()
+ end
+
+ def graph
+ g = RDF::Graph.new
+ @repo.each {|st| g << st if st.context.nil? }
+ g
+ end
+
+ def each_statement(&block); @repo.each_statement(&block); end
+
+ def add_debug(node, message = "")
+ message = message + yield if block_given?
+ @trace ||= []
+ @trace << "#{node}: #{message}"
+ #STDERR.puts "#{node}: #{message}"
+ end
+
+ def trace; @trace.join("\n"); end
+
+ def load(elements)
+ result = nil
+ elements.each do |context, ttl|
+ case context
+ when :default
+ @inputDocument = ttl
+ @repo << parse(ttl)
+ when :result
+ @outputDocument = ttl
+ result = parse(ttl)
+ end
+ end
+
+ result
+ end
+
+ def parse(ttl)
+ RDF::Graph.new << RDF::Turtle::Reader.new(ttl, :prefixes => {
+ :foaf => RDF::FOAF.to_uri,
+ :owl => RDF::OWL.to_uri,
+ :rdf => RDF.to_uri,
+ :rdfa => RDF::RDFA.to_uri,
+ :rdfs => RDF::RDFS.to_uri,
+ :xsd => RDF::XSD.to_uri,
+ :ex => RDF::URI("http://example.org/vocab#"),
+ nil => "http://example.org/",
+ })
+ end
+end
+
+describe RDF::Microdata::Expansion do
+
+ describe :owl_entailment do
+ {
+ "empty" => {
+ :default => %q(),
+ :result => %q()
+ },
+ "simple" => {
+ :default => %q(:a a rdfs:Class .),
+ :result => %q(:a a rdfs:Class .)
+ },
+ "prp-spo1" => {
+ :default => %q(
+ <#me> :name "Gregg Kellogg" .
+ :name rdfs:subPropertyOf foaf:name .
+ ),
+ :result => %q(
+ <#me> :name "Gregg Kellogg"; foaf:name "Gregg Kellogg" .
+ :name rdfs:subPropertyOf foaf:name .
+ )
+ },
+ "prp-eqp1" => {
+ :default => %q(
+ <#me> :name "Gregg Kellogg" .
+ :name owl:equivalentProperty foaf:name .
+ ),
+ :result => %q(
+ <#me> :name "Gregg Kellogg"; foaf:name "Gregg Kellogg" .
+ :name owl:equivalentProperty foaf:name .
+ )
+ },
+ "prp-eqp2" => {
+ :default => %q(
+ <#me> foaf:name "Gregg Kellogg" .
+ :name owl:equivalentProperty foaf:name .
+ ),
+ :result => %q(
+ <#me> :name "Gregg Kellogg"; foaf:name "Gregg Kellogg" .
+ :name owl:equivalentProperty foaf:name .
+ )
+ },
+ }.each do |test, elements|
+ it test do
+ mt = ExpansionTester.new(test)
+ result = mt.load(elements)
+ mt.send(:owl_entailment, mt.repo)
+ mt.graph.should be_equivalent_graph(result, mt)
+ end
+ end
+ end
+
+ describe :expand do
+ {
+ "simple" => {
+ :default => %q(<document> rdfa:usesVocabulary ex: .),
+ :result => %q(<document> rdfa:usesVocabulary ex: .)
+ },
+ "prp-spo1" => {
+ :default => %q(
+ <document> rdfa:usesVocabulary ex: .
+ <#me> ex:name "Gregg Kellogg" .
+ ex:name rdfs:subPropertyOf foaf:name .
+ ),
+ :result => %q(
+ <document> rdfa:usesVocabulary ex: .
+ <#me> ex:name "Gregg Kellogg";
+ foaf:name "Gregg Kellogg" .
+ ex:name rdfs:subPropertyOf foaf:name .
+ )
+ },
+ "prp-eqp1" => {
+ :default => %q(
+ <document> rdfa:usesVocabulary ex: .
+ <#me> ex:name "Gregg Kellogg" .
+ ex:name owl:equivalentProperty foaf:name .
+ ),
+ :result => %q(
+ <document> rdfa:usesVocabulary ex: .
+ <#me> ex:name "Gregg Kellogg";
+ foaf:name "Gregg Kellogg" .
+ ex:name owl:equivalentProperty foaf:name .
+ )
+ },
+ "prp-eqp2" => {
+ :default => %q(
+ <document> rdfa:usesVocabulary ex: .
+ <#me> foaf:name "Gregg Kellogg" .
+ ex:name owl:equivalentProperty foaf:name .
+ ),
+ :result => %q(
+ <document> rdfa:usesVocabulary ex: .
+ <#me> ex:name "Gregg Kellogg";
+ foaf:name "Gregg Kellogg" .
+ ex:name owl:equivalentProperty foaf:name .
+ )
+ },
+ }.each do |test, elements|
+ it test do
+ mt = ExpansionTester.new(test)
+ result = mt.load(elements)
+ vocab = RDF::URI("http://example.org/vocab#")
+ graph = RDF::Graph.new
+ RDF::Graph.should_receive(:new).at_least(1).times.and_return(graph)
+ graph = mt.expand
+ graph.should be_equivalent_graph(result, mt)
+ end
+ end
+ end
+
+ context "with empty graph" do
+ it "returns an empty graph" do
+ rdfa = %q(<http></http>)
+ parse(rdfa).should be_equivalent_graph("", :trace => @debug)
+ end
+ end
+
+ context "with graph not referencing vocabularies" do
+ it "returns unexpanded input" do
+ rdfa = %(
+ <html prefix="doap: http://usefulinc.com/ns/doap#">
+ <body about="" typeof="doap:Project">
+ <p>Project description for <span property="doap:name">RDF::RDFa</span>.</p>
+ <dl>
+ <dt>Creator</dt><dd>
+ <a href="http://greggkellogg.net/foaf#me"
+ rel="dc:creator">
+ Gregg Kellogg
+ </a>
+ </dd>
+ </dl>
+ </body>
+ </html>
+ )
+ ttl = %(
+ @prefix doap: <http://usefulinc.com/ns/doap#> .
+ @prefix dc: <http://purl.org/dc/terms/> .
+
+ <> a doap:Project;
+ doap:name "RDF::RDFa";
+ dc:creator <http://greggkellogg.net/foaf#me> .
+ )
+ parse(rdfa).should be_equivalent_graph(ttl, :trace => @debug)
+ end
+ end
+
+ context "with @vocab" do
+ it "returns unexpanded input" do
+ rdfa = %(
+ <html vocab="http://usefulinc.com/ns/doap#">
+ <body about="" typeof="Project">
+ <p>Project description for <span property="name">RDF::RDFa</span>.</p>
+ <dl>
+ <dt>Creator</dt><dd>
+ <a href="http://greggkellogg.net/foaf#me"
+ rel="dc:creator">
+ Gregg Kellogg
+ </a>
+ </dd>
+ </dl>
+ </body>
+ </html>
+ )
+ ttl = %(
+ @prefix doap: <http://usefulinc.com/ns/doap#> .
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+ @prefix wn: <http://xmlns.com/wordnet/1.6/> .
+ @prefix foaf: <http://xmlns.com/foaf/0.1/> .
+ @prefix rdfa: <http://www.w3.org/ns/rdfa#> .
+ @prefix dc: <http://purl.org/dc/terms/> .
+
+ <> a doap:Project, wn:Project, foaf:Project;
+ rdfa:usesVocabulary <http://usefulinc.com/ns/doap#>;
+ doap:name "RDF::RDFa";
+ rdfs:label "RDF::RDFa";
+ dc:creator <http://greggkellogg.net/foaf#me> .
+ )
+ parse(rdfa).should be_equivalent_graph(ttl, :trace => @debug)
+ end
+ end
+
+ def parse(input, options = {})
+ @debug = options[:debug] || []
+ RDF::Graph.new << RDF::RDFa::Reader.new(input, options.merge(
+ :debug => @debug, :vocab_expansion => true, :vocab_repository => nil
+ ))
+ end
+end
View
88 spec/reader_spec.rb
@@ -712,6 +712,94 @@
end
end
+ context "vocabulary expansion" do
+ it "expands if vocab_expansion is true" do
+ md = %q(
+ <div itemscope='' itemtype='http://expansion/MainType'>
+ <link itemprop='subPropertyOf' href='http://expansion/AdditionalType' />
+ </div>
+ )
+ ttl = %q(
+ <> <http://www.w3.org/ns/md#item> (
+ [ a <http://expansion/MainType>,
+ <http://expansion/AdditionalType>;
+ <http://expansion/subPropertyOf>
+ <http://expansion/AdditionalType>]
+ );
+ <http://www.w3.org/ns/rdfa#usesVocabulary>
+ <http://expansion/> .
+ <http://expansion/subPropertyOf>
+ <http://www.w3.org/2000/01/rdf-schema#subPropertyOf>
+ <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> .
+ )
+
+ parse(md, :vocab_expansion => true).should be_equivalent_graph(ttl, :trace => @debug)
+ end
+
+ it "expands by default" do
+ md = %q(
+ <div itemscope='' itemtype='http://expansion/MainType'>
+ <link itemprop='subPropertyOf' href='http://expansion/AdditionalType' />
+ </div>
+ )
+ ttl = %q(
+ <> <http://www.w3.org/ns/md#item> (
+ [ a <http://expansion/MainType>,
+ <http://expansion/AdditionalType>;
+ <http://expansion/subPropertyOf>
+ <http://expansion/AdditionalType>]
+ );
+ <http://www.w3.org/ns/rdfa#usesVocabulary>
+ <http://expansion/> .
+ <http://expansion/subPropertyOf>
+ <http://www.w3.org/2000/01/rdf-schema#subPropertyOf>
+ <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> .
+ )
+
+ parse(md).should be_equivalent_graph(ttl, :trace => @debug)
+ end
+
+ it "expands equivalentProperty" do
+ md = %q(
+ <div itemscope='' itemtype='http://expansion/MainType'>
+ <link itemprop='equivalentProperty' href='http://expansion/AdditionalType' />
+ </div>
+ )
+ ttl = %q(
+ <> <http://www.w3.org/ns/md#item> (
+ [ a <http://expansion/MainType>,
+ <http://expansion/AdditionalType>;
+ <http://expansion/equivalentProperty>
+ <http://expansion/MainType>,
+ <http://expansion/AdditionalType>]
+ ); <http://www.w3.org/ns/rdfa#usesVocabulary> <http://expansion/> <http://expansion/equivalentProperty>
+ <http://www.w3.org/2002/07/owl#equivalentProperty>
+ <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> .
+ )
+
+ parse(md, :vocab_expansion => true).should be_equivalent_graph(ttl, :trace => @debug)
+ end
+
+ it "does not expand if vocab_expansion is false" do
+ md = %q(
+ <div itemscope='' itemtype='http://expansion/MainType'>
+ <link itemprop='equivalentProperty' href='http://expansion/AdditionalType' />
+ </div>
+ )
+ ttl = %q(
+ <> <http://www.w3.org/ns/md#item> (
+ [ a <http://expansion/MainType>;
+ <http://expansion/equivalentProperty>
+ <http://expansion/AdditionalType>]
+ ); <http://www.w3.org/ns/rdfa#usesVocabulary> <http://expansion/> <http://expansion/equivalentProperty>
+ <http://www.w3.org/2002/07/owl#equivalentProperty>
+ <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> .
+ )
+
+ parse(md, :vocab_expansion => false).should be_equivalent_graph(ttl, :trace => @debug)
+ end
+ end
+
context "test-files" do
Dir.glob(File.join(File.expand_path(File.dirname(__FILE__)), "test-files", "*.html")).each do |md|
it "parses #{md}" do
View
12 spec/test-files/test-registry.json
@@ -36,5 +36,17 @@
"list": {"multipleValues": "list"},
"typed": {"datatype": "http://typed"}
}
+ },
+ "http://expansion/": {
+ "propertyURI": "vocabulary",
+ "multipleValues": "unordered",
+ "properties": {
+ "equivalentProperty": {
+ "equivalentProperty": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
+ },
+ "subPropertyOf": {
+ "subPropertyOf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
+ }
+ }
}
}

0 comments on commit 5ed6645

Please sign in to comment.