sparql 3.0.2 → 3.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +189 -74
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/bin/sparql +44 -24
- data/lib/rack/sparql.rb +1 -1
- data/lib/rack/sparql/conneg.rb +3 -3
- data/lib/sinatra/sparql.rb +5 -5
- data/lib/sparql.rb +17 -16
- data/lib/sparql/algebra.rb +15 -23
- data/lib/sparql/algebra/aggregate.rb +4 -4
- data/lib/sparql/algebra/evaluatable.rb +2 -2
- data/lib/sparql/algebra/expression.rb +70 -44
- data/lib/sparql/algebra/extensions.rb +181 -34
- data/lib/sparql/algebra/operator.rb +44 -23
- data/lib/sparql/algebra/operator/abs.rb +2 -2
- data/lib/sparql/algebra/operator/add.rb +3 -3
- data/lib/sparql/algebra/operator/alt.rb +4 -4
- data/lib/sparql/algebra/operator/and.rb +7 -7
- data/lib/sparql/algebra/operator/asc.rb +3 -3
- data/lib/sparql/algebra/operator/ask.rb +4 -14
- data/lib/sparql/algebra/operator/avg.rb +13 -4
- data/lib/sparql/algebra/operator/base.rb +10 -10
- data/lib/sparql/algebra/operator/bgp.rb +2 -2
- data/lib/sparql/algebra/operator/bnode.rb +5 -5
- data/lib/sparql/algebra/operator/bound.rb +3 -3
- data/lib/sparql/algebra/operator/ceil.rb +2 -2
- data/lib/sparql/algebra/operator/clear.rb +3 -3
- data/lib/sparql/algebra/operator/coalesce.rb +3 -13
- data/lib/sparql/algebra/operator/compare.rb +8 -8
- data/lib/sparql/algebra/operator/concat.rb +4 -4
- data/lib/sparql/algebra/operator/construct.rb +4 -14
- data/lib/sparql/algebra/operator/contains.rb +2 -2
- data/lib/sparql/algebra/operator/copy.rb +3 -3
- data/lib/sparql/algebra/operator/count.rb +3 -3
- data/lib/sparql/algebra/operator/create.rb +3 -3
- data/lib/sparql/algebra/operator/dataset.rb +6 -17
- data/lib/sparql/algebra/operator/datatype.rb +1 -1
- data/lib/sparql/algebra/operator/day.rb +1 -1
- data/lib/sparql/algebra/operator/delete.rb +9 -7
- data/lib/sparql/algebra/operator/delete_data.rb +3 -3
- data/lib/sparql/algebra/operator/delete_where.rb +6 -6
- data/lib/sparql/algebra/operator/desc.rb +1 -1
- data/lib/sparql/algebra/operator/describe.rb +3 -13
- data/lib/sparql/algebra/operator/distinct.rb +4 -14
- data/lib/sparql/algebra/operator/divide.rb +1 -1
- data/lib/sparql/algebra/operator/drop.rb +3 -3
- data/lib/sparql/algebra/operator/encode_for_uri.rb +3 -3
- data/lib/sparql/algebra/operator/equal.rb +2 -2
- data/lib/sparql/algebra/operator/exists.rb +5 -5
- data/lib/sparql/algebra/operator/exprlist.rb +3 -13
- data/lib/sparql/algebra/operator/extend.rb +19 -18
- data/lib/sparql/algebra/operator/filter.rb +6 -16
- data/lib/sparql/algebra/operator/floor.rb +2 -2
- data/lib/sparql/algebra/operator/graph.rb +6 -17
- data/lib/sparql/algebra/operator/greater_than.rb +5 -5
- data/lib/sparql/algebra/operator/greater_than_or_equal.rb +5 -5
- data/lib/sparql/algebra/operator/group.rb +25 -25
- data/lib/sparql/algebra/operator/group_concat.rb +6 -6
- data/lib/sparql/algebra/operator/hours.rb +1 -1
- data/lib/sparql/algebra/operator/if.rb +5 -15
- data/lib/sparql/algebra/operator/in.rb +4 -14
- data/lib/sparql/algebra/operator/insert.rb +7 -5
- data/lib/sparql/algebra/operator/insert_data.rb +3 -3
- data/lib/sparql/algebra/operator/iri.rb +1 -1
- data/lib/sparql/algebra/operator/is_blank.rb +1 -1
- data/lib/sparql/algebra/operator/is_iri.rb +1 -1
- data/lib/sparql/algebra/operator/is_literal.rb +1 -1
- data/lib/sparql/algebra/operator/is_numeric.rb +1 -1
- data/lib/sparql/algebra/operator/join.rb +12 -10
- data/lib/sparql/algebra/operator/lang.rb +1 -1
- data/lib/sparql/algebra/operator/lang_matches.rb +3 -3
- data/lib/sparql/algebra/operator/lcase.rb +2 -2
- data/lib/sparql/algebra/operator/left_join.rb +19 -12
- data/lib/sparql/algebra/operator/less_than.rb +5 -5
- data/lib/sparql/algebra/operator/less_than_or_equal.rb +5 -5
- data/lib/sparql/algebra/operator/load.rb +3 -3
- data/lib/sparql/algebra/operator/max.rb +13 -4
- data/lib/sparql/algebra/operator/md5.rb +1 -1
- data/lib/sparql/algebra/operator/min.rb +13 -4
- data/lib/sparql/algebra/operator/minus.rb +12 -11
- data/lib/sparql/algebra/operator/minutes.rb +1 -1
- data/lib/sparql/algebra/operator/modify.rb +4 -4
- data/lib/sparql/algebra/operator/month.rb +1 -1
- data/lib/sparql/algebra/operator/move.rb +3 -3
- data/lib/sparql/algebra/operator/multiply.rb +1 -1
- data/lib/sparql/algebra/operator/negate.rb +1 -1
- data/lib/sparql/algebra/operator/not.rb +1 -1
- data/lib/sparql/algebra/operator/not_equal.rb +2 -2
- data/lib/sparql/algebra/operator/notexists.rb +4 -4
- data/lib/sparql/algebra/operator/notin.rb +4 -14
- data/lib/sparql/algebra/operator/notoneof.rb +5 -6
- data/lib/sparql/algebra/operator/now.rb +1 -1
- data/lib/sparql/algebra/operator/or.rb +7 -7
- data/lib/sparql/algebra/operator/order.rb +6 -16
- data/lib/sparql/algebra/operator/path.rb +6 -5
- data/lib/sparql/algebra/operator/path_opt.rb +16 -16
- data/lib/sparql/algebra/operator/path_plus.rb +8 -8
- data/lib/sparql/algebra/operator/path_star.rb +4 -4
- data/lib/sparql/algebra/operator/plus.rb +3 -3
- data/lib/sparql/algebra/operator/prefix.rb +10 -10
- data/lib/sparql/algebra/operator/project.rb +4 -14
- data/lib/sparql/algebra/operator/rand.rb +1 -1
- data/lib/sparql/algebra/operator/reduced.rb +4 -14
- data/lib/sparql/algebra/operator/regex.rb +6 -6
- data/lib/sparql/algebra/operator/replace.rb +4 -4
- data/lib/sparql/algebra/operator/reverse.rb +4 -4
- data/lib/sparql/algebra/operator/round.rb +2 -2
- data/lib/sparql/algebra/operator/same_term.rb +8 -5
- data/lib/sparql/algebra/operator/sample.rb +11 -4
- data/lib/sparql/algebra/operator/seconds.rb +1 -1
- data/lib/sparql/algebra/operator/seq.rb +5 -6
- data/lib/sparql/algebra/operator/sequence.rb +4 -4
- data/lib/sparql/algebra/operator/sha1.rb +1 -1
- data/lib/sparql/algebra/operator/sha256.rb +1 -1
- data/lib/sparql/algebra/operator/sha384.rb +1 -1
- data/lib/sparql/algebra/operator/sha512.rb +1 -1
- data/lib/sparql/algebra/operator/slice.rb +4 -14
- data/lib/sparql/algebra/operator/str.rb +1 -1
- data/lib/sparql/algebra/operator/strafter.rb +2 -2
- data/lib/sparql/algebra/operator/strbefore.rb +2 -2
- data/lib/sparql/algebra/operator/strdt.rb +2 -2
- data/lib/sparql/algebra/operator/strends.rb +2 -2
- data/lib/sparql/algebra/operator/strlang.rb +2 -2
- data/lib/sparql/algebra/operator/strlen.rb +2 -2
- data/lib/sparql/algebra/operator/strstarts.rb +2 -2
- data/lib/sparql/algebra/operator/struuid.rb +1 -1
- data/lib/sparql/algebra/operator/substr.rb +4 -4
- data/lib/sparql/algebra/operator/subtract.rb +1 -1
- data/lib/sparql/algebra/operator/sum.rb +6 -4
- data/lib/sparql/algebra/operator/table.rb +3 -3
- data/lib/sparql/algebra/operator/timezone.rb +1 -1
- data/lib/sparql/algebra/operator/tz.rb +1 -1
- data/lib/sparql/algebra/operator/ucase.rb +2 -2
- data/lib/sparql/algebra/operator/union.rb +9 -8
- data/lib/sparql/algebra/operator/update.rb +4 -4
- data/lib/sparql/algebra/operator/using.rb +4 -4
- data/lib/sparql/algebra/operator/uuid.rb +1 -1
- data/lib/sparql/algebra/operator/with.rb +7 -7
- data/lib/sparql/algebra/operator/year.rb +1 -1
- data/lib/sparql/algebra/query.rb +2 -2
- data/lib/sparql/algebra/update.rb +2 -2
- data/lib/sparql/algebra/version.rb +1 -1
- data/lib/sparql/extensions.rb +11 -17
- data/lib/sparql/grammar.rb +113 -13
- data/lib/sparql/grammar/meta.rb +2340 -907
- data/lib/sparql/grammar/parser11.rb +57 -52
- data/lib/sparql/grammar/terminals11.rb +2 -0
- data/lib/sparql/results.rb +73 -46
- data/lib/sparql/version.rb +1 -1
- metadata +46 -63
@@ -6,8 +6,8 @@ module SPARQL::Grammar
|
|
6
6
|
##
|
7
7
|
# A parser for the SPARQL 1.1 grammar.
|
8
8
|
#
|
9
|
-
# @see
|
10
|
-
# @see
|
9
|
+
# @see https://www.w3.org/TR/sparql11-query/#grammar
|
10
|
+
# @see https://en.wikipedia.org/wiki/LR_parser
|
11
11
|
class Parser
|
12
12
|
include SPARQL::Grammar::Meta
|
13
13
|
include SPARQL::Grammar::Terminals
|
@@ -586,7 +586,7 @@ module SPARQL::Grammar
|
|
586
586
|
production(:GroupGraphPatternSub) do |input, data, callback|
|
587
587
|
debug("GroupGraphPatternSub") {"q #{data[:query].inspect}"}
|
588
588
|
|
589
|
-
res = case data[:query].length
|
589
|
+
res = case Array(data[:query]).length
|
590
590
|
when 0 then SPARQL::Algebra::Operator::BGP.new
|
591
591
|
when 1 then data[:query].first
|
592
592
|
when 2
|
@@ -701,9 +701,9 @@ module SPARQL::Grammar
|
|
701
701
|
end
|
702
702
|
end
|
703
703
|
|
704
|
-
# [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
|
704
|
+
# [60] Bind ::= 'BIND' '(' (Expression || EmbTP) 'AS' Var ')'
|
705
705
|
production(:Bind) do |input, data, callback|
|
706
|
-
add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
|
706
|
+
add_prod_datum :extend, [(data[:Expression] || data[:pattern]).unshift(data[:Var].first)]
|
707
707
|
end
|
708
708
|
|
709
709
|
# [61] InlineData ::= 'VALUES' DataBlock
|
@@ -867,13 +867,21 @@ module SPARQL::Grammar
|
|
867
867
|
add_prod_datum(:path, data[:path])
|
868
868
|
end
|
869
869
|
|
870
|
-
# [
|
870
|
+
# [177] AnnotationPattern ::= '{|' PropertyListNotEmpty '|}'
|
871
|
+
start_production(:AnnotationPattern) do |input, data, callback|
|
872
|
+
data[:TriplesNode] = prod_data[:pattern].first
|
873
|
+
end
|
874
|
+
production(:AnnotationPattern) do |input, data, callback|
|
875
|
+
add_prod_datum(:pattern, data[:pattern])
|
876
|
+
end
|
877
|
+
|
878
|
+
# [80] Object ::= GraphNode | EmbTP
|
871
879
|
production(:Object) do |input, data, callback|
|
872
|
-
object = data[:
|
880
|
+
object = data[:GraphNode] || data[:EmbTP]
|
881
|
+
add_prod_datum(:pattern, data[:pattern])
|
873
882
|
if object
|
874
883
|
if prod_data[:Verb]
|
875
884
|
add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
|
876
|
-
add_prod_datum(:pattern, data[:pattern])
|
877
885
|
elsif prod_data[:VerbPath]
|
878
886
|
add_prod_datum(:path,
|
879
887
|
SPARQL::Algebra::Expression(:path,
|
@@ -1104,6 +1112,11 @@ module SPARQL::Grammar
|
|
1104
1112
|
data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
|
1105
1113
|
end
|
1106
1114
|
|
1115
|
+
# [106s] VarOrTermOrEmbTP ::= Var | GraphTerm | EmbTP
|
1116
|
+
production(:VarOrTermOrEmbTP) do |input, data, callback|
|
1117
|
+
data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
|
1118
|
+
end
|
1119
|
+
|
1107
1120
|
# [107] VarOrIri ::= Var | iri
|
1108
1121
|
production(:VarOrIri) do |input, data, callback|
|
1109
1122
|
data.values.each {|v| add_prod_datum(:VarOrIri, v)}
|
@@ -1119,6 +1132,22 @@ module SPARQL::Grammar
|
|
1119
1132
|
data[:NIL])
|
1120
1133
|
end
|
1121
1134
|
|
1135
|
+
# [174] EmbTP ::= '<<' EmbSubjectOrObject Verb EmbSubjectOrObject '>>'
|
1136
|
+
production(:EmbTP) do |input, data, callback|
|
1137
|
+
subject, object = data[:EmbSubjectOrObject]
|
1138
|
+
predicate = data[:Verb]
|
1139
|
+
add_pattern(:EmbTP,
|
1140
|
+
subject: subject,
|
1141
|
+
predicate: predicate,
|
1142
|
+
object: object)
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
# [175] EmbSubjectOrObject ::= Var | BlankNode | iri | RDFLiteral
|
1146
|
+
# | NumericLiteral | BooleanLiteral | EmbTP
|
1147
|
+
production(:EmbSubjectOrObject) do |input, data, callback|
|
1148
|
+
data.values.each {|v| add_prod_datum(:EmbSubjectOrObject, v)}
|
1149
|
+
end
|
1150
|
+
|
1122
1151
|
# [110] Expression ::= ConditionalOrExpression
|
1123
1152
|
production(:Expression) do |input, data, callback|
|
1124
1153
|
add_prod_datum(:Expression, data[:Expression])
|
@@ -1415,7 +1444,7 @@ module SPARQL::Grammar
|
|
1415
1444
|
str = lit.delete(:string)
|
1416
1445
|
lit[:datatype] = lit.delete(:iri) if lit[:iri]
|
1417
1446
|
lit[:language] = lit.delete(:language).last.downcase if lit[:language]
|
1418
|
-
input[:literal] = RDF::Literal.new(str, lit) if str
|
1447
|
+
input[:literal] = RDF::Literal.new(str, **lit) if str
|
1419
1448
|
end
|
1420
1449
|
end
|
1421
1450
|
|
@@ -1458,25 +1487,19 @@ module SPARQL::Grammar
|
|
1458
1487
|
# definitions.
|
1459
1488
|
# @option options [Boolean] :validate (false)
|
1460
1489
|
# whether to validate the parsed statements and values
|
1461
|
-
# @option options [
|
1462
|
-
#
|
1463
|
-
# @option options [Boolean] :debug
|
1464
|
-
# Detailed debug output
|
1490
|
+
# @option options [Logger, #write, #<<] :logger
|
1491
|
+
# Record error/info/debug output
|
1465
1492
|
# @yield [parser] `self`
|
1466
1493
|
# @yieldparam [SPARQL::Grammar::Parser] parser
|
1467
1494
|
# @yieldreturn [void] ignored
|
1468
1495
|
# @return [SPARQL::Grammar::Parser]
|
1469
|
-
def initialize(input = nil, options
|
1496
|
+
def initialize(input = nil, **options, &block)
|
1470
1497
|
@input = case input
|
1471
1498
|
when IO, StringIO then input.read
|
1472
1499
|
else input.to_s.dup
|
1473
1500
|
end
|
1474
1501
|
@input.encode!(Encoding::UTF_8) if @input.respond_to?(:encode!)
|
1475
1502
|
@options = {anon_base: "b0", validate: false}.merge(options)
|
1476
|
-
@options[:debug] ||= case
|
1477
|
-
when options[:progress] then 2
|
1478
|
-
when options[:validate] then 1
|
1479
|
-
end
|
1480
1503
|
|
1481
1504
|
debug("base IRI") {base_uri.inspect}
|
1482
1505
|
debug("validate") {validate?.inspect}
|
@@ -1527,30 +1550,17 @@ module SPARQL::Grammar
|
|
1527
1550
|
# @param [Symbol, #to_s] prod The starting production for the parser.
|
1528
1551
|
# It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
|
1529
1552
|
# @return [Array]
|
1530
|
-
# @see
|
1531
|
-
# @see
|
1553
|
+
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
1554
|
+
# @see https://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
|
1532
1555
|
def parse(prod = START)
|
1533
|
-
ll1_parse(@input,
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
message = args.to_sse
|
1542
|
-
d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
|
1543
|
-
str = "[#{lineno}](#{level})#{d_str}#{message}".chop
|
1544
|
-
case @options[:debug]
|
1545
|
-
when Array
|
1546
|
-
@options[:debug] << str unless level > 2
|
1547
|
-
when TrueClass
|
1548
|
-
$stderr.puts str
|
1549
|
-
when Integer
|
1550
|
-
$stderr.puts(str) if level <= @options[:debug]
|
1551
|
-
end
|
1552
|
-
end
|
1553
|
-
end
|
1556
|
+
ll1_parse(@input,
|
1557
|
+
prod.to_sym,
|
1558
|
+
branch: BRANCH,
|
1559
|
+
first: FIRST,
|
1560
|
+
follow: FOLLOW,
|
1561
|
+
whitespace: WS,
|
1562
|
+
**@options
|
1563
|
+
)
|
1554
1564
|
|
1555
1565
|
# The last thing on the @prod_data stack is the result
|
1556
1566
|
@result = case
|
@@ -1718,9 +1728,7 @@ module SPARQL::Grammar
|
|
1718
1728
|
|
1719
1729
|
if id
|
1720
1730
|
@vars[id] ||= begin
|
1721
|
-
|
1722
|
-
v.distinguished = distinguished
|
1723
|
-
v
|
1731
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
1724
1732
|
end
|
1725
1733
|
else
|
1726
1734
|
unless distinguished
|
@@ -1728,9 +1736,7 @@ module SPARQL::Grammar
|
|
1728
1736
|
id = @nd_var_gen
|
1729
1737
|
@nd_var_gen = id.succ
|
1730
1738
|
end
|
1731
|
-
|
1732
|
-
v.distinguished = distinguished
|
1733
|
-
v
|
1739
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
1734
1740
|
end
|
1735
1741
|
end
|
1736
1742
|
|
@@ -1758,7 +1764,7 @@ module SPARQL::Grammar
|
|
1758
1764
|
end
|
1759
1765
|
|
1760
1766
|
# Create a literal
|
1761
|
-
def literal(value, options
|
1767
|
+
def literal(value, **options)
|
1762
1768
|
options = options.dup
|
1763
1769
|
# Internal representation is to not use xsd:string, although it could arguably go the other way.
|
1764
1770
|
options.delete(:datatype) if options[:datatype] == RDF::XSD.string
|
@@ -1767,7 +1773,7 @@ module SPARQL::Grammar
|
|
1767
1773
|
"options: #{options.inspect}, " +
|
1768
1774
|
"validate: #{validate?.inspect}, "
|
1769
1775
|
end
|
1770
|
-
RDF::Literal.new(value,
|
1776
|
+
RDF::Literal.new(value, validate: validate?, **options)
|
1771
1777
|
end
|
1772
1778
|
|
1773
1779
|
# Take collection of objects and create RDF Collection using rdf:first, rdf:rest and rdf:nil
|
@@ -1798,7 +1804,7 @@ module SPARQL::Grammar
|
|
1798
1804
|
#
|
1799
1805
|
# @param [String] production Production generating pattern
|
1800
1806
|
# @param [Hash{Symbol => Object}] options
|
1801
|
-
def add_pattern(production, options)
|
1807
|
+
def add_pattern(production, **options)
|
1802
1808
|
progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
|
1803
1809
|
triple = {}
|
1804
1810
|
options.each_pair do |r, v|
|
@@ -1880,8 +1886,7 @@ module SPARQL::Grammar
|
|
1880
1886
|
avf.first
|
1881
1887
|
else
|
1882
1888
|
# Allocate a temporary variable for this function, and retain the mapping for outside the group
|
1883
|
-
av = RDF::Query::Variable.new(".#{agg}")
|
1884
|
-
av.distinguished = false
|
1889
|
+
av = RDF::Query::Variable.new(".#{agg}", distinguished: false)
|
1885
1890
|
agg += 1
|
1886
1891
|
aggregates << [av, function]
|
1887
1892
|
av
|
data/lib/sparql/results.rb
CHANGED
@@ -14,28 +14,38 @@ module SPARQL
|
|
14
14
|
##
|
15
15
|
# Generate Solutions as JSON
|
16
16
|
# @return [String]
|
17
|
-
# @see
|
17
|
+
# @see https://www.w3.org/TR/rdf-sparql-json-res/
|
18
18
|
def to_json
|
19
19
|
require 'json' unless defined?(::JSON)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
{
|
28
|
-
|
29
|
-
|
30
|
-
{n => {type: "typed-literal", datatype: s.datatype.to_s, value: s.to_s }}
|
31
|
-
elsif s.language
|
32
|
-
{n => {type: "literal", "xml:lang" => s.language.to_s, value: s.to_s }}
|
33
|
-
else
|
34
|
-
{n => {type: "literal", value: s.to_s }}
|
35
|
-
end
|
20
|
+
|
21
|
+
format = ->(value) do
|
22
|
+
case value
|
23
|
+
when RDF::URI then {type: "uri", value: value.to_s }
|
24
|
+
when RDF::Node then {type: "bnode", value: value.id }
|
25
|
+
when RDF::Literal
|
26
|
+
if value.datatype?
|
27
|
+
{type: "typed-literal", datatype: value.datatype.to_s, value: value.to_s }
|
28
|
+
elsif value.language?
|
29
|
+
{type: "literal", "xml:lang" => value.language.to_s, value: value.to_s }
|
36
30
|
else
|
37
|
-
{}
|
31
|
+
{type: "literal", value: value.to_s }
|
38
32
|
end
|
33
|
+
when RDF::Statement
|
34
|
+
{
|
35
|
+
type: 'triple',
|
36
|
+
value: {
|
37
|
+
subject: format.call(value.subject),
|
38
|
+
predicate: format.call(value.predicate),
|
39
|
+
object: format.call(value.object)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
bindings = self.map do |solution|
|
46
|
+
variable_names.inject({}) do |memo, n|
|
47
|
+
rep = format.call(solution[n])
|
48
|
+
rep ? memo.merge(n => rep) : memo
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
@@ -48,12 +58,36 @@ module SPARQL
|
|
48
58
|
##
|
49
59
|
# Generate Solutions as XML
|
50
60
|
# @return [String]
|
51
|
-
# @see
|
61
|
+
# @see https://www.w3.org/TR/rdf-sparql-XMLres/
|
52
62
|
def to_xml
|
53
63
|
require 'builder' unless defined?(::Builder)
|
54
64
|
|
55
65
|
xml = ::Builder::XmlMarkup.new(indent: 2)
|
56
66
|
xml.instruct!
|
67
|
+
|
68
|
+
format = ->(s) do
|
69
|
+
case s
|
70
|
+
when RDF::URI
|
71
|
+
xml.uri(s.to_s)
|
72
|
+
when RDF::Node
|
73
|
+
xml.bnode(s.id)
|
74
|
+
when RDF::Literal
|
75
|
+
if s.datatype?
|
76
|
+
xml.literal(s.to_s, "datatype" => s.datatype.to_s)
|
77
|
+
elsif s.language
|
78
|
+
xml.literal(s.to_s, "xml:lang" => s.language.to_s)
|
79
|
+
else
|
80
|
+
xml.literal(s.to_s)
|
81
|
+
end
|
82
|
+
when RDF::Statement
|
83
|
+
xml.triple do
|
84
|
+
xml.subject {format.call(s.subject)}
|
85
|
+
xml.predicate {format.call(s.predicate)}
|
86
|
+
xml.object {format.call(s.object)}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
57
91
|
xml.sparql(xmlns: "http://www.w3.org/2005/sparql-results#") do
|
58
92
|
xml.head do
|
59
93
|
variable_names.each do |n|
|
@@ -67,20 +101,7 @@ module SPARQL
|
|
67
101
|
s = solution[n]
|
68
102
|
next unless s
|
69
103
|
xml.binding(name: n) do
|
70
|
-
|
71
|
-
when RDF::URI
|
72
|
-
xml.uri(s.to_s)
|
73
|
-
when RDF::Node
|
74
|
-
xml.bnode(s.id)
|
75
|
-
when RDF::Literal
|
76
|
-
if s.datatype?
|
77
|
-
xml.literal(s.to_s, "datatype" => s.datatype.to_s)
|
78
|
-
elsif s.language
|
79
|
-
xml.literal(s.to_s, "xml:lang" => s.language.to_s)
|
80
|
-
else
|
81
|
-
xml.literal(s.to_s)
|
82
|
-
end
|
83
|
-
end
|
104
|
+
format.call(s)
|
84
105
|
end
|
85
106
|
end
|
86
107
|
end
|
@@ -118,10 +139,9 @@ module SPARQL
|
|
118
139
|
##
|
119
140
|
# Generate Solutions as CSV
|
120
141
|
# @return [String]
|
121
|
-
# @see
|
122
|
-
def to_csv
|
142
|
+
# @see https://www.w3.org/TR/2013/REC-sparql11-results-csv-tsv-20130321/
|
143
|
+
def to_csv(bnode_map: {})
|
123
144
|
require 'csv' unless defined?(::CSV)
|
124
|
-
bnode_map = {}
|
125
145
|
bnode_gen = "_:a"
|
126
146
|
CSV.generate(row_sep: "\r\n") do |csv|
|
127
147
|
csv << variable_names.to_a
|
@@ -134,8 +154,12 @@ module SPARQL
|
|
134
154
|
bnode_gen = bnode_gen.succ
|
135
155
|
this
|
136
156
|
end
|
157
|
+
when RDF::Statement
|
158
|
+
RDF::Query::Solutions(
|
159
|
+
RDF::Query::Solution.new(subject: term.subject, predicate: term.predicate, object: term.object)
|
160
|
+
).to_csv(bnode_map: bnode_map).split.last.strip
|
137
161
|
else
|
138
|
-
solution[n].to_s
|
162
|
+
solution[n].to_s.strip
|
139
163
|
end
|
140
164
|
end
|
141
165
|
end
|
@@ -144,11 +168,9 @@ module SPARQL
|
|
144
168
|
##
|
145
169
|
# Generate Solutions as TSV
|
146
170
|
# @return [String]
|
147
|
-
# @see
|
171
|
+
# @see https://www.w3.org/TR/2013/REC-sparql11-results-csv-tsv-20130321/
|
148
172
|
def to_tsv
|
149
173
|
require 'csv' unless defined?(::CSV)
|
150
|
-
bnode_map = {}
|
151
|
-
bnode_gen = "_:a"
|
152
174
|
results = [
|
153
175
|
variable_names.map {|v| "?#{v}"}.join("\t")
|
154
176
|
] + self.map do |solution|
|
@@ -156,10 +178,15 @@ module SPARQL
|
|
156
178
|
case term = solution[n]
|
157
179
|
when RDF::Literal::Integer, RDF::Literal::Decimal, RDF::Literal::Double
|
158
180
|
term.canonicalize.to_s
|
181
|
+
when RDF::Statement
|
182
|
+
emb_stmt = RDF::Query::Solutions(
|
183
|
+
RDF::Query::Solution.new(subject: term.subject, predicate: term.predicate, object: term.object)
|
184
|
+
).to_tsv.split("\n").last.strip
|
185
|
+
emb_stmt.gsub(/[\t\n\r]/, "\t" => '\t', "\n" => '\n', "\r" => '\r')
|
159
186
|
when nil
|
160
187
|
""
|
161
188
|
else
|
162
|
-
RDF::NTriples.serialize(term)
|
189
|
+
RDF::NTriples.serialize(term).strip.gsub(/[\t\n\r]/, "\t" => '\t', "\n" => '\n', "\r" => '\r')
|
163
190
|
end
|
164
191
|
end.join("\t")
|
165
192
|
end
|
@@ -185,7 +212,7 @@ module SPARQL
|
|
185
212
|
# @return [String]
|
186
213
|
# String with serialized results and `#content_type`
|
187
214
|
# @raise [RDF::WriterError] when inappropriate formatting options are used
|
188
|
-
def serialize_results(solutions, options
|
215
|
+
def serialize_results(solutions, **options)
|
189
216
|
format = options[:format].to_sym if options[:format]
|
190
217
|
content_type = options[:content_type].to_s.split(';').first
|
191
218
|
content_types = Array(options[:content_types] || '*/*')
|
@@ -226,7 +253,7 @@ module SPARQL
|
|
226
253
|
when RDF::Queryable
|
227
254
|
begin
|
228
255
|
require 'linkeddata'
|
229
|
-
rescue LoadError
|
256
|
+
rescue LoadError
|
230
257
|
require 'rdf/ntriples'
|
231
258
|
end
|
232
259
|
fmt = RDF::Format.for(format ? format.to_sym : {content_type: content_type})
|
@@ -236,7 +263,7 @@ module SPARQL
|
|
236
263
|
end
|
237
264
|
format ||= fmt.to_sym
|
238
265
|
content_type ||= fmt.content_type.first
|
239
|
-
results = solutions.dump(format, options)
|
266
|
+
results = solutions.dump(format, **options)
|
240
267
|
raise RDF::WriterError, "Unknown format #{fmt.inspect} for #{solutions.class}" unless results
|
241
268
|
results
|
242
269
|
when RDF::Query::Solutions
|
@@ -280,7 +307,7 @@ module SPARQL
|
|
280
307
|
# @param [Array<String>] available
|
281
308
|
# @return [String]
|
282
309
|
#
|
283
|
-
# @see
|
310
|
+
# @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
284
311
|
def first_content_type(acceptable, available)
|
285
312
|
return acceptable.first if available.empty?
|
286
313
|
available.flatten!
|
@@ -306,7 +333,7 @@ module SPARQL
|
|
306
333
|
# May also be an RDF::Writer content_type to serialize DESCRIBE or CONSTRUCT results
|
307
334
|
# @return [String]
|
308
335
|
# String with serialized results and #content_type
|
309
|
-
def serialize_exception(exception, options
|
336
|
+
def serialize_exception(exception, **options)
|
310
337
|
format = options[:format]
|
311
338
|
content_type = options[:content_type]
|
312
339
|
content_type ||= SPARQL::Results::MIME_TYPES[format]
|
data/lib/sparql/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module SPARQL
|
2
2
|
module VERSION
|
3
|
-
VERSION_FILE = File.
|
3
|
+
VERSION_FILE = File.expand_path("../../../VERSION", __FILE__)
|
4
4
|
MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chomp.split(".")
|
5
5
|
|
6
6
|
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|