Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implemented support for namespaces

  • Loading branch information...
commit 092235306a24e2cee1800c0738e2a86bbd3c9ad7 1 parent 6afe56a
@StevenLooman authored
View
3  lib/child_state.js
@@ -6,11 +6,12 @@ var State = require('./state');
/**
* State representing a child-axis
*/
-function ChildState(axis, name, predicates) {
+function ChildState(axis, namespace, name, predicates) {
this.id = this._generateId();
this.abbrevAxis = '/';
this.axis = 'child';
+ this.namespace = namespace;
this.name = name;
this.predicates = this._initPredicates(predicates);
}
View
9 lib/saxpath.js
@@ -53,14 +53,15 @@ util.inherits(SaXPath, events.EventEmitter);
*/
SaXPath.prototype._buildState = function(part) {
var axis = part[0];
- var name = part[1];
- var predicates = part[2];
+ var namespace = part[1];
+ var name = part[2];
+ var predicates = part[3];
// build state dependent on axis
if (axis === '/') {
- return new ChildState(axis, name, predicates);
+ return new ChildState(axis, namespace, name, predicates);
} else if (axis === '//') {
- return new SelfOrDescendantState(axis, name, predicates);
+ return new SelfOrDescendantState(axis, namespace, name, predicates);
} else {
throw new Error('Unsupported axis');
}
View
3  lib/self_or_descendant_state.js
@@ -6,12 +6,13 @@ var State = require('./state');
/**
* State representing a self-or-descendant-axis
*/
-function SelfOrDescendantState(axis, name, predicates) {
+function SelfOrDescendantState(axis, namespace, name, predicates) {
this.doFork = true;
this.id = this._generateId();
this.abbrevAxis = '//';
this.axis = 'self-or-descendant';
+ this.namespace = namespace;
this.name = name;
this.predicates = this._initPredicates(predicates);
}
View
12 lib/state.js
@@ -18,7 +18,7 @@ State.prototype._initPredicates = function(predicates) {
State.prototype._matchesName = function(node) {
- return node.name === this.name;
+ return node.name === this._namespaceToString() + this.name;
};
State.prototype._matchesPredicate = function(node) {
@@ -44,6 +44,14 @@ State.prototype._matchesPredicate = function(node) {
};
+State.prototype._namespaceToString = function() {
+ if (!this.namespace) {
+ return '';
+ }
+
+ return this.namespace + ':';
+};
+
State.prototype._predicatesToString = function() {
var pred = '';
if (this.predicates.length > 0) {
@@ -71,7 +79,7 @@ State.prototype._predicatesToString = function() {
* toString
*/
State.prototype.toString = function() {
- return this.abbrevAxis + this.name + this._predicatesToString();
+ return this.abbrevAxis + this._namespaceToString() + this.name + this._predicatesToString();
};
View
102 lib/xpath_parser.js
@@ -39,6 +39,7 @@ module.exports = (function(){
var parseFunctions = {
"start": parse_start,
"axis": parse_axis,
+ "namespace": parse_namespace,
"name": parse_name,
"predicate": parse_predicate,
"expr": parse_expr,
@@ -102,18 +103,25 @@ module.exports = (function(){
}
function parse_start() {
- var result0, result1, result2, result3;
+ var result0, result1, result2, result3, result4;
var pos0;
pos0 = pos;
result1 = parse_axis();
if (result1 !== null) {
- result2 = parse_name();
+ result2 = parse_namespace();
+ result2 = result2 !== null ? result2 : "";
if (result2 !== null) {
- result3 = parse_predicate();
- result3 = result3 !== null ? result3 : "";
+ result3 = parse_name();
if (result3 !== null) {
- result1 = [result1, result2, result3];
+ result4 = parse_predicate();
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ result1 = [result1, result2, result3, result4];
+ } else {
+ result1 = null;
+ pos = pos0;
+ }
} else {
result1 = null;
pos = pos0;
@@ -133,12 +141,19 @@ module.exports = (function(){
pos0 = pos;
result1 = parse_axis();
if (result1 !== null) {
- result2 = parse_name();
+ result2 = parse_namespace();
+ result2 = result2 !== null ? result2 : "";
if (result2 !== null) {
- result3 = parse_predicate();
- result3 = result3 !== null ? result3 : "";
+ result3 = parse_name();
if (result3 !== null) {
- result1 = [result1, result2, result3];
+ result4 = parse_predicate();
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ result1 = [result1, result2, result3, result4];
+ } else {
+ result1 = null;
+ pos = pos0;
+ }
} else {
result1 = null;
pos = pos0;
@@ -184,31 +199,92 @@ module.exports = (function(){
return result0;
}
+ function parse_namespace() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (/^[a-z_]/i.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-z_]i");
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ if (/^[a-z_]/i.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-z_]i");
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, str) { return str.join(""); })(pos0, result0[0]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
function parse_name() {
var result0, result1;
var pos0;
pos0 = pos;
- if (/^[a-z]/i.test(input.charAt(pos))) {
+ if (/^[a-z_]/i.test(input.charAt(pos))) {
result1 = input.charAt(pos);
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
- matchFailed("[a-z]i");
+ matchFailed("[a-z_]i");
}
}
if (result1 !== null) {
result0 = [];
while (result1 !== null) {
result0.push(result1);
- if (/^[a-z]/i.test(input.charAt(pos))) {
+ if (/^[a-z_]/i.test(input.charAt(pos))) {
result1 = input.charAt(pos);
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
- matchFailed("[a-z]i");
+ matchFailed("[a-z_]i");
}
}
}
View
21 lib/xpath_parser.pegjs
@@ -1,26 +1,29 @@
start
- = (axis name predicate?)+
+ = (axis namespace? name predicate?)+
axis
- = '//' / '/'
+ = '//' / '/'
+
+namespace
+ = str:[a-z_]i+ ':' { return str.join(""); }
name
- = str:[a-z]i+ { return str.join(""); }
+ = str:[a-z_]i+ { return str.join(""); }
predicate
- = '[' expr ']'
+ = '[' expr ']'
expr
- = attribute_ref op (string_literal / number_literal)
+ = attribute_ref op (string_literal / number_literal)
attribute_ref
- = '@' name
+ = '@' name
op
- = '='
+ = '='
string_literal
- = '"' str:[a-z]i+ '"' { return str.join(""); }
+ = '"' str:[a-z]i+ '"' { return str.join(""); }
number_literal
- = str:[0-9]+ { return str.join(""); }
+ = str:[0-9]+ { return str.join(""); }
View
5 test/namespace.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<root xmlns:test="http://localhost/namespaces/test">
+ <test:node>
+ </test:node>
+</root>
View
24 test/saxpath.js
@@ -206,4 +206,28 @@ describe('SaXPath', function() {
done();
}
});
+
+ it('should be able to match nodes with namespaces in //test:node', function(done) {
+ var fileStream = fs.createReadStream('test/namespace.xml');
+ var recorder = new TapeRecorder();
+ var saxParser = sax.createStream(true);
+ var streamer = new saxpath.SaXPath(saxParser, '//test:node', recorder);
+
+ saxParser.on('end', testNodesRecorded);
+ fileStream.pipe(saxParser);
+
+ function testNodesRecorded() {
+ assert.equal(recorder.box.length, 1);
+
+ var tape;
+ var i;
+ for (i = 0; i < 1; ++i) {
+ tape = recorder.box[i];
+ assert.ok(tape.length > 0);
+ assert.equal(tape[1].openTag.name, 'test:node');
+ }
+
+ done();
+ }
+ });
});
Please sign in to comment.
Something went wrong with that request. Please try again.