前回の問題についてSPARQLのEditorであるEricさんに直接聞いてみたところ、いろいろと教えてもらえた。
詳細はまとめてArticlesの方に書くが(今頃2005年最初の記事だ)、結論としては、氏が製作しているalgaeを使うか(rdf:BagのようにCollectionを扱える)、スマートではないにしてもOPTIONALを並べるかのどちらかだそうだ。OPTIONALを使う場合は最後がブランクノードかどうがをチェックして、もしそうだった場合はもう一度クエリを行えば、取りこぼしは一応無くなる、と教えてくれた。
少なくとも現在策定中のSPRQL1にalgaeのような拡張関数を盛り込むことは無いらしい。仮に盛り込むとしたら、SPARQL2以降だそうだ。
今のところJenaでSPARQLingすると1個前のWDの形式でXML出力されるので、今後のことも考えて最新のWD版に変換するXSLを書いてみた。サーバから古い形式で返事が返ってきて困る場合は役に立つかも。
結構適当なので間違ってたら適当に修正を。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rslt1="http://www.w3.org/2001/sw/DataAccess/rf1/result"
xmlns:rslt2="http://www.w3.org/2001/sw/DataAccess/rf1/result2"
xmlns="http://www.w3.org/2001/sw/DataAccess/rf1/result2">
<xsl:output omit-xml-declaration="no" version="1.0" method="xml" indent="no" encoding="UTF-8"/>
<xsl:template match="rslt1:sparql">
<sparql>
<xsl:apply-templates/>
</sparql>
</xsl:template>
<xsl:template match="rslt1:head">
<head>
<xsl:apply-templates/>
</head>
</xsl:template>
<xsl:template match="rslt1:variable">
<variable name="{@name}"/>
</xsl:template>
<xsl:template match="rslt1:results">
<results>
<xsl:apply-templates/>
</results>
</xsl:template>
<xsl:template match="rslt1:result">
<result>
<xsl:for-each select="*">
<binding name="{local-name()}">
<xsl:choose>
<xsl:when test="@bound = 'false'">
<unbound/>
</xsl:when>
<xsl:when test="@uri">
<uri><xsl:value-of select="@uri"/></uri>
</xsl:when>
<xsl:when test="@bnodeid">
<bnode><xsl:value-of select="@bnodeid"/></bnode>
</xsl:when>
<xsl:otherwise>
<literal>
<xsl:if test="@xml:lang">
<xsl:copy-of select="@xml:lang"/>
</xsl:if>
<xsl:if test="@datatype">
<xsl:copy-of select="@datatype"/>
</xsl:if>
<xsl:value-of select="."/>
</literal>
</xsl:otherwise>
</xsl:choose>
</binding>
</xsl:for-each>
</result>
</xsl:template>
</xsl:stylesheet>