rdf-ext / rdf-parser-csvw

CSV on the Web parser
MIT License
16 stars 4 forks source link

Null cells emitting triples when valueUrl is present #45

Open rossbowen opened 2 years ago

rossbowen commented 2 years ago

If I have a CSV file containing an empty cell, and the related column has a valueUrl, the template is being evaluated using an empty string and emitting a triple.

_:c14n5 <http://example.org/b> <http://example.org/> . 
# If valueUrl wasn't present, no triple would be emitted.

nulls.csv:

a,b
100,200
300,

nulls.csv-metadata.json:

{
    "@context": "http://www.w3.org/ns/csvw",
    "url": "nulls.csv",
    "tableSchema": {
        "columns": [
            {
                "titles": "a",
                "name": "a",
                "propertyUrl": "http://example.org/a",
                "valueUrl": "http://example.org/{a}"
            },
            {
                "titles": "b",
                "name": "b",
                "propertyUrl": "http://example.org/b",
                "valueUrl": "http://example.org/{b}"
            }
        ]
    }
}

Some example code:

const fs = require('fs')
const path = require('path')
const rdf = require('rdf-ext')
const CsvwParser = require('..')
const JsonLdParser = require('@rdfjs/parser-jsonld')

function datasetFromJsonLdFs(filename) {
    const parser = new JsonLdParser({ factory: rdf })
    return rdf.dataset().import(parser.import(fs.createReadStream(path.resolve(filename))))
}

const csvFile = "nulls.csv"
const basePath = path.dirname(csvFile)
const baseName = path.basename(csvFile, '.csv')
const metadataFile = path.join(basePath, baseName + '.csv-metadata.json')
const outputFile = path.join(basePath, baseName + '.nt')
const id = baseName.slice(4, 7)

datasetFromJsonLdFs(metadataFile).then((metadata) => {
    const parser = new CsvwParser({
        factory: rdf,
        baseIRI: path.basename(csvFile),
        metadata: metadata,
        timezone: 'UTC'
    })
    const input = fs.createReadStream(csvFile)
    const stream = parser.import(input)
    rdf.dataset().import(stream).then((actual) => {
        console.log(actual.toCanonical())
    })
})