@igea/oac_backend 1.0.19 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -10,10 +10,13 @@ const configFuseki = config.fuseki || {
|
|
|
10
10
|
"port": "3030",
|
|
11
11
|
"dataset": "oac"
|
|
12
12
|
}
|
|
13
|
-
const
|
|
13
|
+
const fusekiUrlDataset = `${configFuseki.protocol}://${configFuseki.host}:${configFuseki.port}/${configFuseki.dataset}`;
|
|
14
|
+
const fusekiUrl = `${fusekiUrlDataset}/sparql`;
|
|
15
|
+
const fusekiUrlUpdate = `${fusekiUrlDataset}/update`;
|
|
14
16
|
const axios = require('axios');
|
|
15
17
|
const Fuseki = require('../models/fuseki');
|
|
16
|
-
const
|
|
18
|
+
const { Parser, transformMode } = require('../models/vocabolaries/parser');
|
|
19
|
+
const VocabParser = Parser.GET_INSTANCE();
|
|
17
20
|
|
|
18
21
|
//---------------------------------------------------------------
|
|
19
22
|
const uploadFolder = path.join(__dirname, '../data/import');
|
|
@@ -47,7 +50,7 @@ const deleteFiles = function(files){
|
|
|
47
50
|
* @param {Array} files - Array of files to be uploaded
|
|
48
51
|
* @returns {Object} - Response object with message and file details
|
|
49
52
|
*
|
|
50
|
-
* curl -X POST -F "files=@vocabolaries.
|
|
53
|
+
* curl -X POST -F "files=@vocabolaries.xml" http://localhost:5000/backend/fuseki/upload/vocabularies
|
|
51
54
|
*
|
|
52
55
|
* */
|
|
53
56
|
router.post('/upload/vocabularies', upload.array('files'), (req, res) => {
|
|
@@ -68,13 +71,32 @@ router.post('/upload/vocabularies', upload.array('files'), (req, res) => {
|
|
|
68
71
|
|
|
69
72
|
if(xmlFiles.length == 1) {
|
|
70
73
|
let xmlFile = uploadedFiles[0];
|
|
71
|
-
VocabParser.
|
|
72
|
-
console.log(
|
|
74
|
+
VocabParser.insertQuery(xmlFile.path).then(query => {
|
|
75
|
+
console.log("Query to insert vocabularies: ", query);
|
|
76
|
+
|
|
73
77
|
deleteFiles(uploadedFiles)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
axios.post(fusekiUrlUpdate, query, {
|
|
81
|
+
headers: {
|
|
82
|
+
'Content-Type': 'application/sparql-update',
|
|
83
|
+
'Accept': 'application/sparql-results+json'
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
.then(response => {
|
|
87
|
+
res.json({
|
|
88
|
+
message: 'File correctly uploaded and vocabularies updated: ' + response.data,
|
|
89
|
+
files: uploadedFiles
|
|
90
|
+
});
|
|
91
|
+
}).catch(error => {
|
|
92
|
+
let message = (error.response?.status + error.response?.data) || error.message
|
|
93
|
+
res.status(500).json({
|
|
94
|
+
message: 'Error from SPARQL end-point: ' + message,
|
|
95
|
+
files: uploadedFiles,
|
|
96
|
+
query
|
|
97
|
+
});
|
|
77
98
|
});
|
|
99
|
+
|
|
78
100
|
}).catch(err => {
|
|
79
101
|
deleteFiles(uploadedFiles)
|
|
80
102
|
console.error('Error transforming XML:', err);
|
|
@@ -7,16 +7,24 @@ const config = require('../../config');
|
|
|
7
7
|
const VocabPrefix = config.fuseki.vocabularies.prefix || 'diagnostica';
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
const transformMode = {
|
|
11
|
+
default: 'default',
|
|
12
|
+
forInsert: 'forInsert'
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
class Parser{
|
|
11
16
|
|
|
12
17
|
static _INSTANCE = null;
|
|
13
18
|
|
|
14
19
|
constructor(){
|
|
15
20
|
let xsdPath = path.join(__dirname, 'vocabolaries.xsd');
|
|
16
|
-
this.xsltPath =
|
|
21
|
+
this.xsltPath = {
|
|
22
|
+
default: path.join(__dirname, 'vocabolaries.xslt'),
|
|
23
|
+
forInsert: path.join(__dirname, 'vocabolaries_for_insert.xslt')
|
|
24
|
+
};
|
|
17
25
|
this.xsdData = fs.readFileSync(xsdPath, 'utf8');
|
|
18
26
|
this.xsdDoc = libxmljs.parseXml(this.xsdData);
|
|
19
|
-
this.xsltData = fs.readFileSync(this.xsltPath, 'utf8');
|
|
27
|
+
//this.xsltData = fs.readFileSync(this.xsltPath, 'utf8');
|
|
20
28
|
//this.xslt = xmlParser.xmlParse(this.xsltData);
|
|
21
29
|
this.xsltDoc = libxmljs.parseXml(this.xsdData);
|
|
22
30
|
}
|
|
@@ -50,11 +58,12 @@ class Parser{
|
|
|
50
58
|
return result
|
|
51
59
|
}
|
|
52
60
|
|
|
53
|
-
transform(xmlPath){
|
|
61
|
+
transform(xmlPath, using=transformMode.default){
|
|
54
62
|
return new Promise((resolve, reject) => {
|
|
63
|
+
let xsltPath = this.xsltPath[using] || this.xsltPath.default;
|
|
55
64
|
try{
|
|
56
65
|
let command = 'xsltproc --stringparam prefix ' + VocabPrefix + ' ';
|
|
57
|
-
command +=
|
|
66
|
+
command += xsltPath + ' ' + xmlPath
|
|
58
67
|
exec(command, (err, stdout, stderr) => {
|
|
59
68
|
if (err) {
|
|
60
69
|
reject(err)
|
|
@@ -81,6 +90,33 @@ class Parser{
|
|
|
81
90
|
});
|
|
82
91
|
}
|
|
83
92
|
|
|
93
|
+
insertQuery(xmlPath){
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
this.transform(xmlPath, transformMode.forInsert).then(terms => {
|
|
96
|
+
let query = `
|
|
97
|
+
PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
|
98
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
99
|
+
|
|
100
|
+
INSERT {
|
|
101
|
+
?term a crm:E55_Type ;
|
|
102
|
+
rdfs:label ?label ;
|
|
103
|
+
crm:P127_has_broader_term ?broader .
|
|
104
|
+
}
|
|
105
|
+
WHERE {
|
|
106
|
+
VALUES (?term ?label ?broader) {
|
|
107
|
+
${terms.join(' \n')}
|
|
108
|
+
}
|
|
109
|
+
FILTER NOT EXISTS {
|
|
110
|
+
?term rdfs:label ?label .
|
|
111
|
+
}
|
|
112
|
+
}`
|
|
113
|
+
resolve(query);
|
|
114
|
+
}).catch(err => {
|
|
115
|
+
reject(err);
|
|
116
|
+
});
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
84
120
|
static GET_INSTANCE(){
|
|
85
121
|
if (Parser._INSTANCE === null) {
|
|
86
122
|
Parser._INSTANCE = new Parser();
|
|
@@ -89,4 +125,4 @@ class Parser{
|
|
|
89
125
|
}
|
|
90
126
|
}
|
|
91
127
|
|
|
92
|
-
module.exports = Parser
|
|
128
|
+
module.exports = { Parser, transformMode };
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<!-- Vocabolario -->
|
|
21
21
|
<xsl:template match="vocabulary">
|
|
22
22
|
<xsl:param name="prefix"/>
|
|
23
|
-
<xsl:variable name="vocab-id" select="@id"/>
|
|
23
|
+
<xsl:variable name="vocab-id" select="normalize-space(@id)"/>
|
|
24
24
|
<xsl:apply-templates select="term">
|
|
25
25
|
<xsl:with-param name="path" select="concat('http://', $prefix, $vocab-id)"/>
|
|
26
26
|
</xsl:apply-templates>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<!-- Term ricorsivo -->
|
|
30
30
|
<xsl:template match="term">
|
|
31
31
|
<xsl:param name="path"/>
|
|
32
|
-
<xsl:variable name="current-id" select="@id"/>
|
|
32
|
+
<xsl:variable name="current-id" select="normalize-space(@id)"/>
|
|
33
33
|
<xsl:variable name="new-path" select="concat($path, '/', $current-id)"/>
|
|
34
34
|
|
|
35
35
|
<xsl:choose>
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
</xsl:when>
|
|
49
49
|
<xsl:otherwise>
|
|
50
50
|
|
|
51
|
-
<xsl:variable name="cid" select="@id"/>
|
|
51
|
+
<xsl:variable name="cid" select="normalize-space(@id)"/>
|
|
52
52
|
<xsl:variable name="npath" select="concat($path, '/', $current-id)"/>
|
|
53
53
|
|
|
54
54
|
<xsl:for-each select="name">
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
3
|
+
version="1.0">
|
|
4
|
+
|
|
5
|
+
<xsl:output method="text" encoding="UTF-8"/>
|
|
6
|
+
|
|
7
|
+
<xsl:param name="prefix"/>
|
|
8
|
+
|
|
9
|
+
<!-- Prendi il prefix e passa ai vocabolari -->
|
|
10
|
+
<xsl:template match="/vocabularies">
|
|
11
|
+
<!--
|
|
12
|
+
<xsl:variable name="prefix" select="prefix/@value"/>
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
<xsl:apply-templates select="vocabulary">
|
|
16
|
+
<xsl:with-param name="prefix" select="concat($prefix,'/vocabularies')"/>
|
|
17
|
+
</xsl:apply-templates>
|
|
18
|
+
</xsl:template>
|
|
19
|
+
|
|
20
|
+
<!-- Vocabolario -->
|
|
21
|
+
<xsl:template match="vocabulary">
|
|
22
|
+
<xsl:param name="prefix"/>
|
|
23
|
+
<xsl:variable name="vocab-id" select="normalize-space(@id)"/>
|
|
24
|
+
<xsl:apply-templates select="term">
|
|
25
|
+
<xsl:with-param name="path" select="concat('http://', $prefix, $vocab-id)"/>
|
|
26
|
+
</xsl:apply-templates>
|
|
27
|
+
</xsl:template>
|
|
28
|
+
|
|
29
|
+
<!-- Term ricorsivo -->
|
|
30
|
+
<xsl:template match="term">
|
|
31
|
+
<xsl:param name="path"/>
|
|
32
|
+
<xsl:variable name="current-id" select="normalize-space(@id)"/>
|
|
33
|
+
<xsl:variable name="new-path" select="concat($path, '/', $current-id)"/>
|
|
34
|
+
|
|
35
|
+
<xsl:choose>
|
|
36
|
+
<!-- Se NON ha sub-terms/term -->
|
|
37
|
+
<xsl:when test="not(sub-terms/term)">
|
|
38
|
+
<xsl:for-each select="name">
|
|
39
|
+
<xsl:value-of select="concat('(', '<',$new-path,'> ')"/>
|
|
40
|
+
<xsl:text>"</xsl:text>
|
|
41
|
+
<xsl:value-of select="."/>
|
|
42
|
+
<xsl:text>"@</xsl:text>
|
|
43
|
+
<xsl:value-of select="@lang"/>
|
|
44
|
+
<xsl:value-of select="concat(' <',$path,'>', ') ')"/>
|
|
45
|
+
<xsl:text> </xsl:text>
|
|
46
|
+
</xsl:for-each>
|
|
47
|
+
</xsl:when>
|
|
48
|
+
<xsl:otherwise>
|
|
49
|
+
|
|
50
|
+
<xsl:variable name="cid" select="normalize-space(@id)"/>
|
|
51
|
+
<xsl:variable name="npath" select="concat($path, '/', $current-id)"/>
|
|
52
|
+
|
|
53
|
+
<xsl:for-each select="name">
|
|
54
|
+
<xsl:value-of select="concat('(','<',$npath,'> ')"/>
|
|
55
|
+
<xsl:text>"</xsl:text>
|
|
56
|
+
<xsl:value-of select="."/>
|
|
57
|
+
<xsl:text>"@</xsl:text>
|
|
58
|
+
<xsl:value-of select="@lang"/>
|
|
59
|
+
<xsl:value-of select="concat(' <',$path,'>',') ')"/>
|
|
60
|
+
<xsl:text> </xsl:text>
|
|
61
|
+
</xsl:for-each>
|
|
62
|
+
|
|
63
|
+
<xsl:apply-templates select="sub-terms/term">
|
|
64
|
+
<xsl:with-param name="prev-path" select="$path"/>
|
|
65
|
+
<xsl:with-param name="path" select="$new-path"/>
|
|
66
|
+
</xsl:apply-templates>
|
|
67
|
+
</xsl:otherwise>
|
|
68
|
+
</xsl:choose>
|
|
69
|
+
</xsl:template>
|
|
70
|
+
|
|
71
|
+
</xsl:stylesheet>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const chai = require('chai');
|
|
2
2
|
const expect = chai.expect;
|
|
3
3
|
const request = require('supertest');
|
|
4
|
-
const Parser = require('../../../src/models/vocabolaries/parser');
|
|
4
|
+
//const Parser = require('../../../src/models/vocabolaries/parser');
|
|
5
|
+
const { Parser, transformMode } = require('../../../src/models/vocabolaries/parser');
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
describe('Vocabolaries.Parsers', () => {
|
|
@@ -23,7 +24,7 @@ describe('Vocabolaries.Parsers', () => {
|
|
|
23
24
|
expect(nodes.length).to.be.equal(10);
|
|
24
25
|
});
|
|
25
26
|
|
|
26
|
-
it('should transform the vocabolaries.xml file', async () => {
|
|
27
|
+
it('should transform the vocabolaries.xml file (default)', async () => {
|
|
27
28
|
const parser = Parser.GET_INSTANCE();
|
|
28
29
|
var terms = await parser.transform(__dirname + '/vocabolaries.xml');
|
|
29
30
|
console.log(terms.filter(n => n.indexOf('P127_has_broader_term') == -1))
|
|
@@ -31,5 +32,19 @@ describe('Vocabolaries.Parsers', () => {
|
|
|
31
32
|
expect(terms[0]).to.be.equal('<http://diagnostica/vocabularies/condizioni-ambientali> a crm:E55_Type rdfs:label "Condizioni ambientali"@it ; crm:P127_has_broader_term <http://diagnostica/vocabularies> .');
|
|
32
33
|
expect(terms[1]).to.be.equal('<http://diagnostica/vocabularies/condizioni-ambientali/ambiente> a crm:E55_Type rdfs:label "Ambiente"@it ; crm:P127_has_broader_term <http://diagnostica/vocabularies/condizioni-ambientali> .');
|
|
33
34
|
});
|
|
35
|
+
|
|
36
|
+
it('should transform the vocabolaries.xml file (for insert)', async () => {
|
|
37
|
+
const parser = Parser.GET_INSTANCE();
|
|
38
|
+
var terms = await parser.transform(__dirname + '/vocabolaries.xml', transformMode.forInsert);
|
|
39
|
+
expect(terms.length).to.be.equal(246);
|
|
40
|
+
expect(terms[0]).to.be.equal('(<http://diagnostica/vocabularies/condizioni-ambientali> "Condizioni ambientali"@it <http://diagnostica/vocabularies>)');
|
|
41
|
+
expect(terms[1]).to.be.equal('(<http://diagnostica/vocabularies/condizioni-ambientali/ambiente> "Ambiente"@it <http://diagnostica/vocabularies/condizioni-ambientali>)');
|
|
42
|
+
});
|
|
34
43
|
|
|
44
|
+
it('should get the insert query for the vocabolaries.xml file', async () => {
|
|
45
|
+
const parser = Parser.GET_INSTANCE();
|
|
46
|
+
var query = await parser.insertQuery(__dirname + '/vocabolaries.xml');
|
|
47
|
+
expect(query.length).to.be.equal(40619);
|
|
48
|
+
});
|
|
49
|
+
|
|
35
50
|
});
|