require File.join(File.dirname(__FILE__), 'spec_helper') include RdfContext FOO_NS = Namespace.new("http://foo/", "foo") describe "XML Serializer" do before(:each) do @graph = Graph.new end describe "with types" do it "should serialize resource without type" do @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/@dc:title" => "foo" ) end it "should serialize resource with type" do @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.Release) @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/foo:Release/@rdf:about" => "http://release/", "/rdf:RDF/foo:Release/@dc:title" =>"foo", "/rdf:RDF/foo:Release/rdf:type" => "" ) end it "should serialize resource with two types as attribute" do @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.Release) @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.XtraRelease) @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/foo:Release/@rdf:about" => "http://release/", "/rdf:RDF/foo:Release/@dc:title" => "foo", "/rdf:RDF/foo:Release/@rdf:type" => FOO_NS.XtraRelease.to_s ) end it "should serialize resource with two types as element" do @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.Release) @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.XtraRelease) @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:max_depth => 1, :attributes => :none), "/rdf:RDF/foo:Release/@rdf:about" => "http://release/", "/rdf:RDF/foo:Release/dc:title" => true, "/rdf:RDF/foo:Release/rdf:type" => %(<rdf:type rdf:resource="#{FOO_NS.XtraRelease}"/>) ) end it "should serialize resource with three types as element" do @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.Release) @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.XtraRelease) @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.XXtraRelease) @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:max_depth => 1, :attributes => :typed), "/rdf:RDF/foo:Release/@rdf:about" => "http://release/", "/rdf:RDF/foo:Release/@dc:title" => true, %(/rdf:RDF/foo:Release/rdf:type[@rdf:resource="#{FOO_NS.XtraRelease}"]) => true, %(/rdf:RDF/foo:Release/rdf:type[@rdf:resource="#{FOO_NS.XXtraRelease}"]) => true ) end end describe "with children" do it "should serialize referenced resource by ref" do @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.Release) @graph.add_triple("http://release/", DC_NS.title, "foo") @graph.add_triple("http://release/contributor", RDF_TYPE, FOO_NS.Contributor) @graph.add_triple("http://release/contributor", DC_NS.title, "bar") @graph.add_triple("http://release/", FOO_NS.releaseContributor, "http://release/contributor") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/foo:Release/@rdf:about" => "http://release/", "/rdf:RDF/foo:Release/@dc:title" => "foo", "/rdf:RDF/foo:Release/foo:releaseContributor/@rdf:resource" => "http://release/contributor", "/rdf:RDF/foo:Contributor/@rdf:about" => "http://release/contributor", "/rdf:RDF/foo:Contributor/@dc:title" => "bar" ) end it "should serialize referenced resource by inclusion" do @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.Release) @graph.add_triple("http://release/", DC_NS.title, "foo") @graph.add_triple("http://release/contributor", RDF_TYPE, FOO_NS.Contributor) @graph.add_triple("http://release/contributor", DC_NS.title, "bar") @graph.add_triple("http://release/", FOO_NS.releaseContributor, "http://release/contributor") check_xpaths( serialize(:max_depth => 3, :attributes => :untyped), "/rdf:RDF/foo:Release/@rdf:about" => "http://release/", "/rdf:RDF/foo:Release/@dc:title" => "foo", "/rdf:RDF/foo:Release/foo:releaseContributor/foo:Contributor/@rdf:about" => "http://release/contributor" ) end end describe "with sequences" do it "should serialize rdf:Seq with rdf:li" do @graph.add_triple("http://example/seq", RDF_TYPE, RDF_NS.Seq) @graph.add_triple("http://example/seq", RDF_NS._1, "http://example/first") @graph.add_triple("http://example/seq", RDF_NS._2, "http://example/second") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/rdf:Seq/@rdf:about" => "http://example/seq", %(/rdf:RDF/rdf:Seq/rdf:li[@rdf:resource="http://example/first"]) => true, %(/rdf:RDF/rdf:Seq/rdf:li[@rdf:resource="http://example/second"]) => true ) end it "should serialize rdf:Seq with multiple rdf:li in proper sequence" do @graph.add_triple("http://example/seq", RDF_TYPE, RDF_NS.Seq) @graph.add_triple("http://example/seq", RDF_NS._2, "http://example/second") @graph.add_triple("http://example/seq", RDF_NS._1, "http://example/first") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/rdf:Seq/@rdf:about" => "http://example/seq", %(/rdf:RDF/rdf:Seq/rdf:li[@rdf:resource="http://example/first"]) => true, %(/rdf:RDF/rdf:Seq/rdf:li[@rdf:resource="http://example/second"]) => true ) end it "should serialize rdf:Bag with multiple rdf:li" do @graph.add_triple("http://example/seq", RDF_TYPE, RDF_NS.Bag) @graph.add_triple("http://example/seq", RDF_NS._2, "http://example/second") @graph.add_triple("http://example/seq", RDF_NS._1, "http://example/first") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/rdf:Bag/@rdf:about" => "http://example/seq", %(/rdf:RDF/rdf:Bag/rdf:li[@rdf:resource="http://example/first"]) => true, %(/rdf:RDF/rdf:Bag/rdf:li[@rdf:resource="http://example/second"]) => true ) end it "should serialize rdf:Alt with multiple rdf:li" do @graph.add_triple("http://example/seq", RDF_TYPE, RDF_NS.Alt) @graph.add_triple("http://example/seq", RDF_NS._2, "http://example/second") @graph.add_triple("http://example/seq", RDF_NS._1, "http://example/first") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/rdf:Alt/@rdf:about" => "http://example/seq", %(/rdf:RDF/rdf:Alt/rdf:li[@rdf:resource="http://example/first"]) => true, %(/rdf:RDF/rdf:Alt/rdf:li[@rdf:resource="http://example/second"]) => true ) end end describe "with lists" do it "should serialize List rdf:first/rdf:rest" do @graph.parse(%(@prefix foo: <http://foo/> . foo:author foo:is (Gregg Barnum Kellogg).), "http://foo/", :type => :ttl) check_xpaths( serialize({}), "/rdf:RDF/rdf:Description/@rdf:about" => "http://foo/author", "/rdf:RDF/rdf:Description/foo:is/@rdf:parseType" => "Collection", %(/rdf:RDF/rdf:Description/foo:is/rdf:Description[@rdf:about="http://foo/#Gregg"]) => true, %(/rdf:RDF/rdf:Description/foo:is/rdf:Description[@rdf:about="http://foo/#Barnum"]) => true, %(/rdf:RDF/rdf:Description/foo:is/rdf:Description[@rdf:about="http://foo/#Kellogg"]) => true, %(//rdf:first) => false ) end it "should serialize resource with multiple rdf:li in proper sequence" do @graph.add_triple("http://example/seq", RDF_TYPE, RDF_NS.Seq) @graph.add_triple("http://example/seq", RDF_NS._2, "http://example/second") @graph.add_triple("http://example/seq", RDF_NS._1, "http://example/first") check_xpaths( serialize(:max_depth => 1, :attributes => :untyped), "/rdf:RDF/rdf:Seq/@rdf:about" => "http://example/seq", %(/rdf:RDF/rdf:Seq/rdf:li[@rdf:resource="http://example/first"]) => true, %(/rdf:RDF/rdf:Seq/rdf:li[@rdf:resource="http://example/second"]) => true ) end end describe "with untyped literals" do it "should seralize as element if :attributes == :none" do @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:attributes => :none), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/dc:title" => "<dc:title>foo</dc:title>" ) end it "should seralize as attribute if :attributes == :untyped or :typed" do @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:attributes => :untyped), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/@dc:title" => "foo" ) check_xpaths( serialize(:attributes => :typed), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/@dc:title" => "foo" ) end it "should output untyped without lang as attribute lang set" do @graph.add_triple("http://release/", DC_NS.title, "foo") check_xpaths( serialize(:attributes => :untyped, :lang => "de"), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/@dc:title" => "foo" ) end describe "with language" do it "should output property for title with language" do @graph.add_triple("http://release/", DC_NS.title, Literal.untyped("foo", "en-us")) check_xpaths( serialize(:attributes => :untyped, :lang => "de"), "/rdf:RDF/@xml:lang" => "de", "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/dc:title" => %(<dc:title xml:lang="en-us">foo</dc:title>) ) end end it "should output untyped as attribute if lang is default" do @graph.add_triple("http://release/", DC_NS.title, Literal.untyped("foo", "de")) check_xpaths( serialize(:attributes => :untyped, :lang => "de"), "/rdf:RDF/@xml:lang" => "de", "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/@dc:title" => "foo" ) end it "should output untyped as property if lang set and no default" do @graph.add_triple("http://release/", DC_NS.title, Literal.untyped("foo", "de")) check_xpaths( serialize(:attributes => :untyped), "/rdf:RDF/@xml:lang" => false, "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/dc:title" => %(<dc:title xml:lang="de">foo</dc:title>) ) end it "should output untyped as property if lang set and not default" do @graph.add_triple("http://release/", DC_NS.title, Literal.untyped("foo", "de")) check_xpaths( serialize(:attributes => :untyped, :lang => "en-us"), "/rdf:RDF/@xml:lang" => "en-us", "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/dc:title" => %(<dc:title xml:lang="de">foo</dc:title>) ) end it "should output multiple untyped attributes values through properties" do @graph.add_triple("http://release/", DC_NS.title, Literal.untyped("foo", "de")) @graph.add_triple("http://release/", DC_NS.title, Literal.untyped("foo", "en-us")) check_xpaths( serialize(:attributes => :untyped, :lang => "en-us"), "/rdf:RDF/@xml:lang" => "en-us", "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/dc:title[lang('de')]" => %(<dc:title xml:lang="de">foo</dc:title>), "/rdf:RDF/rdf:Description/dc:title[lang('en-us')]" => %(<dc:title>foo</dc:title>) ) end it "should output typed node as attribute" do @graph.add_triple("http://release/", DC_NS.title, Literal.typed("foo", XSD_NS.string)) check_xpaths( serialize(:attributes => :untyped), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/dc:title" => %(<dc:title rdf:datatype="#{XSD_NS.string}">foo</dc:title>) ) check_xpaths( serialize(:attributes => :typed), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/@dc:title" => "foo" ) end it "should output multiple typed values through properties" do @graph.add_triple("http://release/", DC_NS.title, Literal.typed("foo", XSD_NS.string)) @graph.add_triple("http://release/", DC_NS.title, Literal.typed("bar", XSD_NS.string)) check_xpaths( serialize(:attributes => :untyped), "/rdf:RDF/rdf:Description/@rdf:about" => "http://release/", "/rdf:RDF/rdf:Description/dc:title[contains(., 'foo')]" => %(<dc:title rdf:datatype="#{XSD_NS.string}">foo</dc:title>), "/rdf:RDF/rdf:Description/dc:title[contains(., 'bar')]" => %(<dc:title rdf:datatype="#{XSD_NS.string}">bar</dc:title>) ) end end describe "with default namespace" do it "should serialize with default namespace" do @graph.add_triple("http://release/", RDF_TYPE, FOO_NS.Release) @graph.add_triple("http://release/", DC_NS.title, "foo") @graph.add_triple("http://release/", FOO_NS.pred, FOO_NS.obj) @graph.bind(Namespace.new(FOO_NS.uri, "")) #$DEBUG = true xml = serialize(:max_depth => 1, :attributes => :untyped) #puts xml xml.should =~ /<Release/ xml.should =~ /<pred/ doc = Nokogiri::XML.parse(xml) doc.at_xpath("/rdf:RDF/#{FOO_NS.prefix}:Release/#{FOO_NS.prefix}:pred/@rdf:resource", doc.namespaces).to_s.should == FOO_NS.obj.to_s end end describe "with base" do it "should generate relative about URI" do @graph.add_triple("http://release/a", FOO_NS.ref, "http://release/b") check_xpaths( serialize(:attributes => :untyped, :base => "http://release/"), "/rdf:RDF/rdf:Description/@rdf:about" => "a", "/rdf:RDF/rdf:Description/foo:ref/@rdf:resource" => "b" ) end end describe "with bnodes" do it "should not generate nodeID attribute unless node is referenced as an object" do @graph.add_triple(BNode.new("a"), DC_NS.title, "foo") check_xpaths( serialize(:attributes => :untyped, :base => "http://release/"), "/rdf:RDF/rdf:Description/@dc:title" => "foo", "/rdf:RDF/rdf:Description/@rdf:nodeID" => false ) end it "should generate a nodeID attribute if node is referenced as an object" do bn = BNode.new("a") @graph.add_triple(bn, DC_NS.title, "foo") @graph.add_triple(bn, OWL_NS.equals, bn) check_xpaths( serialize(:attributes => :untyped, :base => "http://release/"), "/rdf:RDF/rdf:Description/@dc:title" => "foo", "/rdf:RDF/rdf:Description/@rdf:nodeID" => /Na$/, "/rdf:RDF/rdf:Description/owl:equals/@rdf:nodeID" => /Na$/ ) end end def check_xpaths(doc, paths) puts doc if $DEBUG || $verbose doc = Nokogiri::XML.parse(doc) #puts "doc: #{doc.to_s}" doc.should be_a(Nokogiri::XML::Document) paths.each_pair do |path, value| puts "xpath: #{path.inspect}" if $DEBUG puts doc.root.at_xpath(path, @namespaces).inspect if $DEBUG case value when false doc.root.at_xpath(path, doc.namespaces).should be_nil when true doc.root.at_xpath(path, doc.namespaces).should_not be_nil when Array doc.root.at_xpath(path, doc.namespaces).to_s.split(" ").should include(*value) when Regexp doc.root.at_xpath(path, doc.namespaces).to_s.should =~ value else doc.root.at_xpath(path, doc.namespaces).to_s.should == value end end # Parse generated graph and compare to source Graph.new.parse(doc, "http://release/", :format => :xml).should be_equivalent_graph(@graph, :about => "http://release/") end # Serialize ntstr to a string and compare against regexps def serialize(options) #$DEBUG = true result = @graph.serialize(options.merge(:format => :xml)) #$DEBUG = false result end end