1

是否可以在没有迭代的情况下在 SPARQL中实现空白节点 skolemization ?在我看来,需要迭代来计算空白节点链,例如:

@prefix : <http://example.com/> .

[ a :A ;
  :p1 [
    a :B
  ]
] .

用于 skolemization 的 SPARQL 更新操作可以从仅在没有空白节点对象的三元组中作为主题出现的空白节点开始:

DELETE {
  ?b1 ?outP ?outO .
  ?inS ?inP ?b1 .
}
INSERT {
  ?iri ?outP ?outO .
  ?inS ?inP ?iri .
}
WHERE {
  {
    SELECT ?b1 (uuid() AS ?iri)
    WHERE {
      {
        SELECT DISTINCT ?b1
        WHERE {
          ?b1 ?p1 [] .
          FILTER isBlank(?b1)
          FILTER NOT EXISTS {
            ?b1 ?p2 ?b2 .
            FILTER isBlank(?b2)
          }
        }
      }
    }
  }
  ?b1 ?outP ?outO .
  OPTIONAL {
    ?inS ?inP ?b1 .
  }
}

可以重复此操作,直到在数据中找不到空白节点:

ASK {
  ?bnode ?p [] .
  FILTER isBlank(?bnode)
}

是否可以在单个 SPARQL 更新操作中避免迭代并实现空白节点 skolemization?

(此外,此方法假定没有“孤立”空白节点(即仅作为对象出现的空白节点)。)

4

1 回答 1

2

我找到了一个两步解决方案,分别计算主题和对象,并将空白节点别名(空白节点和 IRI 之间的链接通过owl:sameAs)存储为中间数据:

PREFIX :    <http://example.com/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>

####################
# Rewrite subjects #
####################

DELETE {
  ?bnode ?p ?o .
}
INSERT {
  ?iri ?p ?o .
  GRAPH :aliases {
    ?bnode owl:sameAs ?iri .
  }
}
WHERE {
  {
    SELECT ?bnode (uuid() AS ?iri)
    WHERE {
      {
        SELECT DISTINCT ?bnode
        WHERE {
          ?bnode ?p [] .
          FILTER isBlank(?bnode)
        }
      }
    }
  }
  ?bnode ?p ?o .
}
;

###################
# Rewrite objects #
###################

DELETE {
  ?s ?p ?bnode .
}
INSERT {
  ?s ?p ?iri .
}
WHERE {
  {
    SELECT ?bnode ?iri
    WHERE {
      {
        SELECT DISTINCT ?bnode
        WHERE {
          [] ?p ?bnode .
          FILTER isBlank(?bnode)
        }
      }
      OPTIONAL {
        GRAPH :aliases {
          ?bnode owl:sameAs ?_iri .
        }
      }
      BIND (coalesce(?_iri, uuid()) AS ?iri)
    }
  }
  ?s ?p ?bnode .
}
;

############################
# Clear blank node aliases #
############################

CLEAR GRAPH :aliases
于 2017-11-28T13:32:30.010 回答