rdfxml-streaming-parser
Advanced tools
Comparing version 1.2.1 to 1.2.2
# Changelog | ||
All notable changes to this project will be documented in this file. | ||
<a name="v1.2.2"></a> | ||
## [v1.2.2](https://github.com/rdfjs/rdfxml-streaming-parser.js/compare/v1.2.1...v1.2.2) - 2019-04-25 | ||
### Fixed | ||
* [Error on unbound prefixes, Closes #12](https://github.com/rdfjs/rdfxml-streaming-parser.js/commit/0931aab22c505cbfdd7ae89fd7fd5065a1cb3555) | ||
* [Validate all created URIs, Closes #11](https://github.com/rdfjs/rdfxml-streaming-parser.js/commit/75588df39b49d6945001d381af76d38ba9add768) | ||
<a name="v1.2.1"></a> | ||
@@ -5,0 +12,0 @@ ## [v1.2.1](https://github.com/rdfjs/rdfxml-streaming-parser.js/compare/v1.2.0...v1.2.1) - 2019-04-02 |
@@ -7,2 +7,3 @@ /// <reference types="node" /> | ||
export declare class RdfXmlParser extends Transform { | ||
static readonly IRI_REGEX: RegExp; | ||
static readonly MIME_TYPE = "application/rdf+xml"; | ||
@@ -56,2 +57,8 @@ static readonly RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; | ||
/** | ||
* Check if the given IRI is valid. | ||
* @param {string} iri A potential IRI. | ||
* @return {boolean} If the given IRI is valid. | ||
*/ | ||
static isValidIri(iri: string): boolean; | ||
/** | ||
* Parses the given text stream into a quad stream. | ||
@@ -74,2 +81,11 @@ * @param {NodeJS.EventEmitter} stream A text stream. | ||
/** | ||
* Convert the given value URI string to a named node. | ||
* | ||
* This will emit an error if the URI is invalid. | ||
* | ||
* @param {string} uri A URI string. | ||
* @return {NamedNode} a named node. | ||
*/ | ||
uriToNamedNode(uri: string): RDF.NamedNode; | ||
/** | ||
* Validate the given value as an NCName: https://www.w3.org/TR/xml-names/#NT-NCName | ||
@@ -76,0 +92,0 @@ * If it is invalid, an error will be emitted. |
@@ -93,2 +93,6 @@ "use strict"; | ||
if (!uri) { | ||
// Error on unbound prefix | ||
if (prefix && prefix !== 'xmlns') { | ||
throw new Error(`The prefix '${prefix}' in term '${term}' was not bound.`); | ||
} | ||
// Fallback to default namespace if no match was found | ||
@@ -121,2 +125,10 @@ uri = defaultNamespace || ''; | ||
/** | ||
* Check if the given IRI is valid. | ||
* @param {string} iri A potential IRI. | ||
* @return {boolean} If the given IRI is valid. | ||
*/ | ||
static isValidIri(iri) { | ||
return RdfXmlParser.IRI_REGEX.test(iri); | ||
} | ||
/** | ||
* Parses the given text stream into a quad stream. | ||
@@ -148,5 +160,20 @@ * @param {NodeJS.EventEmitter} stream A text stream. | ||
valueToUri(value, activeTag) { | ||
return this.dataFactory.namedNode(relative_to_absolute_iri_1.resolve(value, activeTag.baseIRI)); | ||
return this.uriToNamedNode(relative_to_absolute_iri_1.resolve(value, activeTag.baseIRI)); | ||
} | ||
/** | ||
* Convert the given value URI string to a named node. | ||
* | ||
* This will emit an error if the URI is invalid. | ||
* | ||
* @param {string} uri A URI string. | ||
* @return {NamedNode} a named node. | ||
*/ | ||
uriToNamedNode(uri) { | ||
// Validate URI | ||
if (!RdfXmlParser.isValidIri(uri)) { | ||
this.emit('error', new Error(`Invalid URI: ${uri}`)); | ||
} | ||
return this.dataFactory.namedNode(uri); | ||
} | ||
/** | ||
* Validate the given value as an NCName: https://www.w3.org/TR/xml-names/#NT-NCName | ||
@@ -174,45 +201,50 @@ * If it is invalid, an error will be emitted. | ||
onTag(tag) { | ||
// Get parent tag | ||
const parentTag = this.activeTagStack.length | ||
? this.activeTagStack[this.activeTagStack.length - 1] : null; | ||
let currentParseType = ParseType.RESOURCE; | ||
if (parentTag) { | ||
parentTag.hadChildren = true; | ||
currentParseType = parentTag.childrenParseType; | ||
} | ||
// Check if this tag needs to be converted to a string | ||
if (parentTag && parentTag.childrenStringTags) { | ||
// Convert this tag to a string | ||
const tagName = tag.name; | ||
let attributes = ''; | ||
for (const attributeKey in tag.attributes) { | ||
attributes += ` ${attributeKey}="${tag.attributes[attributeKey]}"`; | ||
try { | ||
// Get parent tag | ||
const parentTag = this.activeTagStack.length | ||
? this.activeTagStack[this.activeTagStack.length - 1] : null; | ||
let currentParseType = ParseType.RESOURCE; | ||
if (parentTag) { | ||
parentTag.hadChildren = true; | ||
currentParseType = parentTag.childrenParseType; | ||
} | ||
const tagContents = `${tagName}${attributes}`; | ||
const tagString = `<${tagContents}>`; | ||
parentTag.childrenStringTags.push(tagString); | ||
// Inherit the array, so that deeper tags are appended to this same array | ||
const stringActiveTag = { childrenStringTags: parentTag.childrenStringTags }; | ||
stringActiveTag.childrenStringEmitClosingTag = `</${tagName}>`; | ||
this.activeTagStack.push(stringActiveTag); | ||
// Halt any further processing | ||
return; | ||
// Check if this tag needs to be converted to a string | ||
if (parentTag && parentTag.childrenStringTags) { | ||
// Convert this tag to a string | ||
const tagName = tag.name; | ||
let attributes = ''; | ||
for (const attributeKey in tag.attributes) { | ||
attributes += ` ${attributeKey}="${tag.attributes[attributeKey]}"`; | ||
} | ||
const tagContents = `${tagName}${attributes}`; | ||
const tagString = `<${tagContents}>`; | ||
parentTag.childrenStringTags.push(tagString); | ||
// Inherit the array, so that deeper tags are appended to this same array | ||
const stringActiveTag = { childrenStringTags: parentTag.childrenStringTags }; | ||
stringActiveTag.childrenStringEmitClosingTag = `</${tagName}>`; | ||
this.activeTagStack.push(stringActiveTag); | ||
// Halt any further processing | ||
return; | ||
} | ||
const activeTag = {}; | ||
if (parentTag) { | ||
// Inherit language scope and baseIRI from parent | ||
activeTag.language = parentTag.language; | ||
activeTag.baseIRI = parentTag.baseIRI; | ||
} | ||
else { | ||
activeTag.baseIRI = this.baseIRI; | ||
} | ||
this.activeTagStack.push(activeTag); | ||
activeTag.ns = RdfXmlParser.parseNamespace(tag, parentTag); | ||
if (currentParseType === ParseType.RESOURCE) { | ||
this.onTagResource(tag, activeTag, parentTag, !parentTag); | ||
} | ||
else { // currentParseType === ParseType.PROPERTY | ||
this.onTagProperty(tag, activeTag, parentTag); | ||
} | ||
} | ||
const activeTag = {}; | ||
if (parentTag) { | ||
// Inherit language scope and baseIRI from parent | ||
activeTag.language = parentTag.language; | ||
activeTag.baseIRI = parentTag.baseIRI; | ||
catch (e) { | ||
this.emit('error', e); | ||
} | ||
else { | ||
activeTag.baseIRI = this.baseIRI; | ||
} | ||
this.activeTagStack.push(activeTag); | ||
activeTag.ns = RdfXmlParser.parseNamespace(tag, parentTag); | ||
if (currentParseType === ParseType.RESOURCE) { | ||
this.onTagResource(tag, activeTag, parentTag, !parentTag); | ||
} | ||
else { // currentParseType === ParseType.PROPERTY | ||
this.onTagProperty(tag, activeTag, parentTag); | ||
} | ||
} | ||
@@ -314,3 +346,3 @@ /** | ||
if (attributeKeyExpanded.prefix !== 'xml' && attributeKeyExpanded.uri) { | ||
predicates.push(this.dataFactory.namedNode(attributeKeyExpanded.uri + attributeKeyExpanded.local)); | ||
predicates.push(this.uriToNamedNode(attributeKeyExpanded.uri + attributeKeyExpanded.local)); | ||
objects.push(attributeValue); | ||
@@ -333,3 +365,3 @@ } | ||
if (typedNode) { | ||
const type = this.dataFactory.namedNode(tagExpanded.uri + tagExpanded.local); | ||
const type = this.uriToNamedNode(tagExpanded.uri + tagExpanded.local); | ||
this.emitTriple(activeTag.subject, this.dataFactory.namedNode(RdfXmlParser.RDF + 'type'), type, parentTag ? parentTag.reifiedStatementId : null); | ||
@@ -371,3 +403,3 @@ } | ||
if (explicitType) { | ||
this.emitTriple(activeTag.subject, this.dataFactory.namedNode(RdfXmlParser.RDF + 'type'), this.dataFactory.namedNode(explicitType), null); | ||
this.emitTriple(activeTag.subject, this.dataFactory.namedNode(RdfXmlParser.RDF + 'type'), this.uriToNamedNode(explicitType), null); | ||
} | ||
@@ -391,6 +423,6 @@ } | ||
} | ||
activeTag.predicate = this.dataFactory.namedNode(tagExpanded.uri + '_' + parentTag.listItemCounter++); | ||
activeTag.predicate = this.uriToNamedNode(tagExpanded.uri + '_' + parentTag.listItemCounter++); | ||
} | ||
else { | ||
activeTag.predicate = this.dataFactory.namedNode(tagExpanded.uri + tagExpanded.local); | ||
activeTag.predicate = this.uriToNamedNode(tagExpanded.uri + tagExpanded.local); | ||
} | ||
@@ -512,3 +544,3 @@ // Check forbidden property element names | ||
attributedProperty = true; | ||
predicates.push(this.dataFactory.namedNode(propertyAttributeKeyExpanded.uri + propertyAttributeKeyExpanded.local)); | ||
predicates.push(this.uriToNamedNode(propertyAttributeKeyExpanded.uri + propertyAttributeKeyExpanded.local)); | ||
objects.push(this.dataFactory.literal(propertyAttributeValue, activeTag.datatype || activeTag.language)); | ||
@@ -630,2 +662,4 @@ } | ||
} | ||
// Regex for valid IRIs | ||
RdfXmlParser.IRI_REGEX = /^([A-Za-z][A-Za-z0-9+-.]*|_):[^ "<>{}|\\\[\]`]*$/; | ||
RdfXmlParser.MIME_TYPE = 'application/rdf+xml'; | ||
@@ -632,0 +666,0 @@ RdfXmlParser.RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; |
{ | ||
"name": "rdfxml-streaming-parser", | ||
"version": "1.2.1", | ||
"version": "1.2.2", | ||
"description": "Streaming RDF/XML parser", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
51457
885