Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
* Other functions are internals exposed for a potential API usage.
*/

var fs = require('fs');
var xml2js = require('xml2js');
var temp = require('temp').track();

var xsdInclusions = require('./lib/xsd-inclusions');
var xsdExtensions = require('./lib/xsd-extensions');
Expand All @@ -22,9 +24,18 @@ exports.xsd2json = function(filePath, callback) {
var builder = new xml2js.Builder();
var xml = builder.buildObject(mergedSchema);

prologWrapper.xsd2jsonWrapper(xml, function(err, schema) {
temp.open('xsd2json2', function(err, info) {
if (err) return callback(err);
callback(null, jsonProcessing.postProcessing(schema));

fs.write(info.fd, xml);
fs.close(info.fd, function(err) {
if (err) return callback(err);

prologWrapper.xsd2jsonWrapper(info.path, function(err, schema) {
if (err) return callback(err);
callback(null, jsonProcessing.postProcessing(schema));
});
});
});
});
};
Expand Down
5 changes: 2 additions & 3 deletions lib/prolog-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ var log = require('winston').loggers.get('xsd2json');
/**
* Wrap the original xsd2json prolog programm in a function call
*
* @param [string] xsd - The XSD schema as a string
* @param [string] xsd - The XSD schema filename
* @param [function] callback - The callback will be run with and optional error and the JSON schema result as a string
*/
exports.xsd2jsonWrapper = function(xsd, callback) {
log.debug('Spawn prolog xsd2json program');
//var swipl = spawn();
var swipl = spawn('swipl', ['-q', '-f', '../prolog-xsd2json/cli.pl', '--'], {
var swipl = spawn('swipl', ['-q', '-f', '../prolog-xsd2json/cli', xsd], {
cwd: __dirname
});

Expand All @@ -36,6 +36,5 @@ exports.xsd2jsonWrapper = function(xsd, callback) {
callback(null, result);
});

swipl.stdin.write(xsd);
swipl.stdin.end();
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"lodash": "^2.4.1",
"lodash-deep": "^1.4.2",
"request": "^2.47.0",
"temp": "^0.8.1",
"winston": "^0.8.3",
"xml2js": "^0.4.4"
},
Expand Down
10 changes: 7 additions & 3 deletions prolog-xsd2json/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
# xsd2json

CHR module to translate an XML Schema into equivalent JSON Schema.
Prolog/CHR module to translate an XML Schema into equivalent JSON Schema.

## Installation

All you need is [SWI-Prolog](http://www.swi-prolog.org/). See there for installation instructions.

## Usage

`xsd2json` provides a command line interface. You can use it via
`xsd2json` provides a command line interface. You can directly execute it via

swipl -q -f cli.pl -- < /path/to/your.xsd
./cli /path/to/your.xsd

or by calling swipl:

swipl -q -f cli /path/to/your.xsd

Unfortunately the command line version is way slower than using `xsd2json` programmatically. The `xsd2json.pl` module provides a predicate `xsd2json/2` which can be used to convert a given XSD file into the equivalent JSON Schema. Call it via `swipl -s xsd2json.pl` followed by

Expand Down
15 changes: 15 additions & 0 deletions prolog-xsd2json/cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/swipl -f -q

:- encoding(utf8).
:- use_module(xsd2json).
:- use_module(library(http/json)).


:- initialization main.

main :-
current_prolog_flag(argv, Argv),
Argv = [Filename|_],
xsd2json(Filename,JSON),
json_write(user_output,JSON),
halt(0).
11 changes: 0 additions & 11 deletions prolog-xsd2json/cli.pl

This file was deleted.

18 changes: 18 additions & 0 deletions prolog-xsd2json/helpers.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
:- module(helpers, [ string_concat/2 ]).


/**
* string_concat/2
* string_concat(List_Of_Strings,Concatenated_String)
*
* Concatenates all strings of a given `List_Of_Strings` to
* `Concatenated_String` by use of the predefined
* `string_concat/3`.
*
* Examples:
* string_concat(['a','b','c'], "abc").
* string_concat([a,b,c],"abc").
*/
string_concat([],'').
string_concat([A],A).
string_concat([A,B|Bs],Result) :- string_concat(A,B,Temp), string_concat([Temp|Bs],Result).
67 changes: 57 additions & 10 deletions prolog-xsd2json/merge_json.pl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
:- encoding(utf8).
:- module(merge_json, [ merge_json/3, merge_json/4, lookup/4 ]).
:- module(merge_json, [ merge_json/3, merge_json/4, merge_facets/3, merge_facet/4, lookup/4 ]).
:- use_module(helpers).


/**
* merge_json/4
Expand All @@ -24,26 +26,40 @@
merge_json(json([]),json(JSON_List2),json(JSON_List2),_On_Conflict).

merge_json(json([Key=Value|Rest_JSON_List1]),json(JSON_List2),json(Merged),On_Conflict) :-
% Key also exists in JSON_List2 and value is equal
lookup(Key,JSON_List2,Value,JSON2_Without_Key),
% Key also exists in JSON_List2
lookup(Key,JSON_List2,Value2,JSON2_Without_Key),
(
Value == Value2,
New_Value = Value
;
% If `Key` is `description` simply concat the values
% by using a \n separator.
Key == description,
string_concat(Value,'\n',ValueNl),
string_concat(ValueNl,Value2,New_Value)
),
merge_json(json(Rest_JSON_List1),json(JSON2_Without_Key),json(Rest_Merged),On_Conflict),
Merged = [Key=Value|Rest_Merged].
Merged = [Key=New_Value|Rest_Merged].

merge_json(json([Key=Value|Rest_JSON_List1]),json(JSON_List2),json(Merged),On_Conflict) :-
% Key also exists in JSON_List2 and value is no atom
lookup(Key,JSON_List2,Value_in_JSON_List2,JSON2_Without_Key),
\+atom(Value),
% If `Key` is `required` or `enum` use union instead of
% the merge_json/3 predicate which would result
% in an append of both lists.
% This might be necessary due to different orders to
% apply the CHR rules.
(
% If `Key` is `required` or `enum` use union instead of
% the merge_json/3 predicate which would result
% in an append of both lists.
% This might be necessary due to different orders to
% apply the CHR rules.
(Key == required; Key == enum),
union(Value,Value_in_JSON_List2,Merged_Value)
;
Key == facets,
merge_facets(Value,Value_in_JSON_List2,Merged_Value)
;
Key \== required,
Key \== enum,
Key \== facets,
merge_json(Value,Value_in_JSON_List2,Merged_Value)
),
% merge the rest of the lists independently of the
Expand Down Expand Up @@ -86,6 +102,37 @@
merge_json(JSON1,JSON2,JSON,hard).


/**
* merge_facets/3.
*/
merge_facets(json([]),json(JSON_List2),json(JSON_List2)).
merge_facets(json(JSON_List1),json([]),json(JSON_List1)) :- JSON_List1 \= [].
merge_facets(json([Key=Value|Rest_JSON_List1]),json(JSON_List2),json(JSON)) :-
lookup(Key,JSON_List2,Value_in_JSON_List2,JSON2_Without_Key),
merge_facet(Key,Value,Value_in_JSON_List2,Merged_Value),
merge_facets(json(Rest_JSON_List1),json(JSON2_Without_Key),json(Rest_Merged)),
JSON = [Key=Merged_Value|Rest_Merged].
merge_facets(json([Key=Value|Rest_JSON_List1]),json(JSON_List2),json(JSON)) :-
\+lookup(Key,JSON_List2,_Value_in_JSON_List2),
merge_facets(json(Rest_JSON_List1),json(JSON_List2),json(Rest_Merged)),
JSON = [Key=Value|Rest_Merged].


/**
* merge_facet/4
* merge_facet(Facet,Value1,Value2,Result_Value)
*/
merge_facet(minLength,A,B,A) :- A >= B.
merge_facet(minLength,A,B,B) :- A < B.
merge_facet(maxLength,A,B,A) :- A =< B.
merge_facet(maxLength,A,B,B) :- A > B.
merge_facet(minimum,A,B,A) :- A >= B.
merge_facet(minimum,A,B,B) :- A < B.
merge_facet(maximum,A,B,A) :- A =< B.
merge_facet(maximum,A,B,B) :- A > B.
merge_facet(pattern,A,B,R) :- string_concat(['(',A,'|',B,')'],R).


/**
* lookup/3
* lookup(Key,Key_Value_List,Value)
Expand Down Expand Up @@ -115,4 +162,4 @@
lookup(Key,[Key=Value|Without_Key],Value,Without_Key).
lookup(Key,[Not_Key=Some_Value|Rest],Value,[Not_Key=Some_Value|Without_Key]) :-
Key \= Not_Key,
lookup(Key,Rest,Value,Without_Key).
lookup(Key,Rest,Value,Without_Key).
Loading