mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
Add character line and column index for easysax parser events
This commit is contained in:
@ -1 +1 @@
|
||||
{"eventType":"StartElement","elementName":"DocumentElement","attributes":{"param":"value"}}{"eventType":"StartElement","elementName":"First.Element","attributes":{"some.attr":"some.value"}}{"eventType":"Text","data":"\n ¶ Some Text ®\n "}{"eventType":"EndElement","elementName":"First.Element"}{"eventType":"StartElement","elementName":"SecondElement","attributes":{"param2":"something"}}{"eventType":"Text","data":"\n Pre-Text "}{"eventType":"StartElement","elementName":"Inline"}{"eventType":"Text","data":"Inlined text"}{"eventType":"EndElement","elementName":"Inline"}{"eventType":"Text","data":" Post-text.\n "}{"eventType":"EndElement","elementName":"SecondElement"}{"eventType":"StartElement","elementName":"entities"}{"eventType":"Text","data":"Xml tags begin with \"<\" and end with \">\" Ampersand is & and apostrophe is '"}{"eventType":"EndElement","elementName":"entities"}{"eventType":"StartElement","elementName":"script"}{"eventType":"CDATA","data":"\nfunction sum(a,b)\n{\n return a+b;\n}\n"}{"eventType":"EndElement","elementName":"script"}{"eventType":"Comment","data":"\n Hello,\n I am a multi-line XML comment.\n"}{"eventType":"EndElement","elementName":"DocumentElement"}
|
||||
{"eventType":"StartElement","position":{"line":2,"column":1},"elementName":"DocumentElement","attributes":{"param":"value"}}{"eventType":"StartElement","position":{"line":3,"column":3},"elementName":"First.Element","attributes":{"some.attr":"some.value"}}{"eventType":"Text","position":{"line":3,"column":41},"data":"\n ¶ Some Text ®\n "}{"eventType":"EndElement","position":{"line":5,"column":3},"elementName":"First.Element"}{"eventType":"StartElement","position":{"line":7,"column":3},"elementName":"SecondElement","attributes":{"param2":"something"}}{"eventType":"Text","position":{"line":7,"column":37},"data":"\n Pre-Text "}{"eventType":"StartElement","position":{"line":8,"column":14},"elementName":"Inline"}{"eventType":"Text","position":{"line":8,"column":22},"data":"Inlined text"}{"eventType":"EndElement","position":{"line":8,"column":34},"elementName":"Inline"}{"eventType":"Text","position":{"line":8,"column":43},"data":" Post-text.\n "}{"eventType":"EndElement","position":{"line":9,"column":3},"elementName":"SecondElement"}{"eventType":"StartElement","position":{"line":10,"column":3},"elementName":"entities"}{"eventType":"Text","position":{"line":10,"column":13},"data":"Xml tags begin with \"<\" and end with \">\" Ampersand is & and apostrophe is '"}{"eventType":"EndElement","position":{"line":10,"column":123},"elementName":"entities"}{"eventType":"StartElement","position":{"line":11,"column":3},"elementName":"script"}{"eventType":"CDATA","position":{"line":12,"column":5},"data":"\nfunction sum(a,b)\n{\n return a+b;\n}\n"}{"eventType":"EndElement","position":{"line":18,"column":3},"elementName":"script"}{"eventType":"Comment","position":{"line":19,"column":3},"data":"\n Hello,\n I am a multi-line XML comment.\n"}{"eventType":"EndElement","position":{"line":23,"column":1},"elementName":"DocumentElement"}
|
@ -469,11 +469,24 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
, stop // используется при разборе "namespace" . если встретился неизвестное пространство то события не генерируются
|
||||
, _nsmatrix
|
||||
, ok
|
||||
, pos = 0, ln = 0, lnStart = -2, lnEnd = -1
|
||||
;
|
||||
|
||||
function getStringNode() {
|
||||
return xml.substring(i, j+1)
|
||||
};
|
||||
function findLineAndColumnFromPos() {
|
||||
while (lnStart < lnEnd && lnEnd < pos) {
|
||||
lnStart = lnEnd;
|
||||
lnEnd = xml.indexOf("\n", lnEnd + 1);
|
||||
++ln;
|
||||
}
|
||||
return { line: ln, column: pos - lnStart };
|
||||
}
|
||||
function position(p) {
|
||||
pos = p;
|
||||
return findLineAndColumnFromPos;
|
||||
}
|
||||
|
||||
while(j !== -1) {
|
||||
stop = stopIndex > 0;
|
||||
@ -487,7 +500,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
if (i === -1) { // конец разбора
|
||||
|
||||
if (nodestack.length) {
|
||||
this.onError('end file');
|
||||
this.onError('end file', position(j));
|
||||
return;
|
||||
};
|
||||
|
||||
@ -495,7 +508,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
};
|
||||
|
||||
if (j !== i && !stop) {
|
||||
ok = this.onTextNode(xml.substring(j, i), unEntities);
|
||||
ok = this.onTextNode(xml.substring(j, i), unEntities, position(j));
|
||||
if (ok === false) return;
|
||||
};
|
||||
|
||||
@ -506,13 +519,13 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
if (w === 91 && xml.substr(i+3, 6) === 'CDATA[') { // 91 == "["
|
||||
j = xml.indexOf(']]>', i);
|
||||
if (j === -1) {
|
||||
this.onError('cdata');
|
||||
this.onError('cdata', position(i));
|
||||
return;
|
||||
};
|
||||
|
||||
//x = xml.substring(i+9, j);
|
||||
if (!stop) {
|
||||
ok = this.onCDATA(xml.substring(i+9, j), false);
|
||||
ok = this.onCDATA(xml.substring(i+9, j), false, position(i));
|
||||
if (ok === false) return;
|
||||
};
|
||||
|
||||
@ -523,13 +536,13 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
if (w === 45 && xml.charCodeAt(i+3) === 45) { // 45 == "-"
|
||||
j = xml.indexOf('-->', i);
|
||||
if (j === -1) {
|
||||
this.onError('expected -->');
|
||||
this.onError('expected -->', position(i));
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
if (this.is_onComment && !stop) {
|
||||
ok = this.onComment(xml.substring(i+4, j), unEntities);
|
||||
ok = this.onComment(xml.substring(i+4, j), unEntities, position(i));
|
||||
if (ok === false) return;
|
||||
};
|
||||
|
||||
@ -539,12 +552,12 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
|
||||
j = xml.indexOf('>', i+1);
|
||||
if (j === -1) {
|
||||
this.onError('expected ">"');
|
||||
this.onError('expected ">"', position(i + 1));
|
||||
return;
|
||||
};
|
||||
|
||||
if (this.is_onAttention && !stop) {
|
||||
ok = this.onAttention(xml.substring(i, j+1), unEntities);
|
||||
ok = this.onAttention(xml.substring(i, j+1), unEntities, position(i));
|
||||
if (ok === false) return;
|
||||
};
|
||||
|
||||
@ -555,12 +568,12 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
if (w === 63) { // "?"
|
||||
j = xml.indexOf('?>', i);
|
||||
if (j === -1) { // error
|
||||
this.onError('...?>');
|
||||
this.onError('...?>', position(i));
|
||||
return;
|
||||
};
|
||||
|
||||
if (this.is_onQuestion) {
|
||||
ok = this.onQuestion(xml.substring(i, j+2));
|
||||
ok = this.onQuestion(xml.substring(i, j+2), position(i));
|
||||
if (ok === false) return;
|
||||
};
|
||||
|
||||
@ -572,7 +585,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
j = xml.indexOf('>', i+1);
|
||||
|
||||
if (j == -1) { // error
|
||||
this.onError('...>');
|
||||
this.onError('...>', position(i + 1));
|
||||
return;
|
||||
};
|
||||
|
||||
@ -589,7 +602,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
|
||||
//console.log()
|
||||
if (xml.substring(i+2, q) !== x) {
|
||||
this.onError('close tagname');
|
||||
this.onError('close tagname', position(i + 2));
|
||||
return;
|
||||
};
|
||||
|
||||
@ -601,7 +614,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
continue;
|
||||
};
|
||||
|
||||
this.onError('close tag');
|
||||
this.onError('close tag', position(i + 2));
|
||||
return;
|
||||
};
|
||||
|
||||
@ -619,7 +632,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
};
|
||||
|
||||
if ( !(w > 96 && w < 123 || w > 64 && w <91) ) {
|
||||
this.onError('first char nodeName');
|
||||
this.onError('first char nodeName', position(i + 1));
|
||||
return;
|
||||
};
|
||||
|
||||
@ -636,7 +649,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
break;
|
||||
};
|
||||
|
||||
this.onError('invalid nodeName');
|
||||
this.onError('invalid nodeName', position(i + 1));
|
||||
return;
|
||||
};
|
||||
|
||||
@ -718,7 +731,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
|
||||
var that = this;
|
||||
ok = this.onStartNode(elem, function() { return that.getAttrs() }, unEntities, tagend
|
||||
, getStringNode
|
||||
, getStringNode, position(i)
|
||||
);
|
||||
|
||||
if (ok === false) {
|
||||
@ -730,7 +743,7 @@ EasySAXParser.prototype.parse = function(xml) {
|
||||
|
||||
if (tagend) {
|
||||
ok = this.onEndNode(elem, unEntities, tagstart
|
||||
, getStringNode
|
||||
, getStringNode, position(i)
|
||||
);
|
||||
|
||||
if (ok === false) {
|
||||
|
20
xml/xml.d.ts
vendored
20
xml/xml.d.ts
vendored
@ -34,6 +34,21 @@ declare module "xml" {
|
||||
static Comment: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a position within string, in line and column form.
|
||||
*/
|
||||
interface Position {
|
||||
/**
|
||||
* The line number. The first line is at index 1.
|
||||
*/
|
||||
line: number;
|
||||
|
||||
/**
|
||||
* The column number. The first character is at index 1.
|
||||
*/
|
||||
column: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides information for a parser event.
|
||||
*/
|
||||
@ -44,6 +59,11 @@ declare module "xml" {
|
||||
*/
|
||||
eventType: string;
|
||||
|
||||
/**
|
||||
* Get the position in the xml string where the event was generated.
|
||||
*/
|
||||
position: Position;
|
||||
|
||||
/**
|
||||
* If namespace processing is enabled, returns the prefix of the element in case the eventType is ParserEventType.StartElement or ParserEventType.EndElement.
|
||||
*/
|
||||
|
35
xml/xml.ts
35
xml/xml.ts
@ -11,14 +11,16 @@ export class ParserEventType implements definition.ParserEventType {
|
||||
|
||||
export class ParserEvent implements definition.ParserEvent {
|
||||
private _eventType: string;
|
||||
private _position: definition.Position;
|
||||
private _prefix: string;
|
||||
private _namespace: string;
|
||||
private _elementName: string;
|
||||
private _attributes: Object;
|
||||
private _data: string;
|
||||
|
||||
constructor(eventType: string, prefix?: string, namespace?: string, elementName?: string, attributes?: Object, data?: string) {
|
||||
constructor(eventType: string, position: definition.Position, prefix?: string, namespace?: string, elementName?: string, attributes?: Object, data?: string) {
|
||||
this._eventType = eventType;
|
||||
this._position = position;
|
||||
this._prefix = prefix;
|
||||
this._namespace = namespace;
|
||||
this._elementName = elementName;
|
||||
@ -29,6 +31,7 @@ export class ParserEvent implements definition.ParserEvent {
|
||||
public toString(): string {
|
||||
return JSON.stringify({
|
||||
eventType: this.eventType,
|
||||
position: this.position,
|
||||
prefix: this.prefix,
|
||||
namespace: this.namespace,
|
||||
elementName: this.elementName,
|
||||
@ -41,6 +44,10 @@ export class ParserEvent implements definition.ParserEvent {
|
||||
return this._eventType;
|
||||
}
|
||||
|
||||
public get position(): definition.Position {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
public get prefix(): string {
|
||||
return this._prefix;
|
||||
}
|
||||
@ -103,12 +110,12 @@ export class XmlParser implements definition.XmlParser {
|
||||
private _processNamespaces: boolean;
|
||||
private _namespaceStack: Array<any>;
|
||||
|
||||
constructor(onEvent: (event: definition.ParserEvent) => void, onError?: (error: Error) => void, processNamespaces?: boolean) {
|
||||
constructor(onEvent: (event: definition.ParserEvent) => void, onError?: (error: Error, position: definition.Position) => void, processNamespaces?: boolean) {
|
||||
this._processNamespaces = processNamespaces;
|
||||
this._parser = new easysax.EasySAXParser();
|
||||
|
||||
var that = this;
|
||||
this._parser.on('startNode', function (elem, attr, uq, str, tagend) {
|
||||
this._parser.on('startNode', function (elem, attr, uq, tagend, str, pos) {
|
||||
var attributes = attr();
|
||||
|
||||
if (attributes === true) {//HACK: For some reason easysax returns the true literal when an element has no attributes.
|
||||
@ -139,15 +146,15 @@ export class XmlParser implements definition.XmlParser {
|
||||
name = resolved.name;
|
||||
}
|
||||
|
||||
onEvent(new ParserEvent(ParserEventType.StartElement, prefix, namespace, name, attributes, undefined));
|
||||
onEvent(new ParserEvent(ParserEventType.StartElement, pos(), prefix, namespace, name, attributes, undefined));
|
||||
});
|
||||
|
||||
this._parser.on('textNode', function (text, uq) {
|
||||
this._parser.on('textNode', function (text, uq, pos) {
|
||||
var data = uq(XmlParser._dereferenceEntities(text));// Decode entity references such as < and >
|
||||
onEvent(new ParserEvent(ParserEventType.Text, undefined, undefined, undefined, undefined, data));
|
||||
onEvent(new ParserEvent(ParserEventType.Text, pos(), undefined, undefined, undefined, undefined, data));
|
||||
});
|
||||
|
||||
this._parser.on('endNode', function (elem, uq, tagstart, str) {
|
||||
this._parser.on('endNode', function (elem, uq, tagstart, str, pos) {
|
||||
|
||||
var prefix = undefined;
|
||||
var namespace = undefined;
|
||||
@ -160,24 +167,24 @@ export class XmlParser implements definition.XmlParser {
|
||||
name = resolved.name;
|
||||
}
|
||||
|
||||
onEvent(new ParserEvent(ParserEventType.EndElement, prefix, namespace, name, undefined, undefined));
|
||||
onEvent(new ParserEvent(ParserEventType.EndElement, pos(), prefix, namespace, name, undefined, undefined));
|
||||
|
||||
if (that._processNamespaces) {
|
||||
that._namespaceStack.pop();
|
||||
}
|
||||
});
|
||||
|
||||
this._parser.on('cdata', function (data) {
|
||||
onEvent(new ParserEvent(ParserEventType.CDATA, undefined, undefined, undefined, undefined, data));
|
||||
this._parser.on('cdata', function (data, res, pos) {
|
||||
onEvent(new ParserEvent(ParserEventType.CDATA, pos(), undefined, undefined, undefined, undefined, data));
|
||||
});
|
||||
|
||||
this._parser.on('comment', function (text) {
|
||||
onEvent(new ParserEvent(ParserEventType.Comment, undefined, undefined, undefined, undefined, text));
|
||||
this._parser.on('comment', function (text, uq, pos) {
|
||||
onEvent(new ParserEvent(ParserEventType.Comment, pos(), undefined, undefined, undefined, undefined, text));
|
||||
});
|
||||
|
||||
if (onError) {
|
||||
this._parser.on('error', function (msg) {
|
||||
onError(new Error(msg));
|
||||
this._parser.on('error', function (msg, pos) {
|
||||
onError(new Error(msg), pos());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user