function XmlStream(stream, encoding) {
events.EventEmitter.call(this);
this._stream = stream;
this._fa = new FiniteAutomata();
this._lastState = 0;
this._startState = {};
this._finalStates = {};
this._emitData = false;
this._bufferLevel = 0;
this._preserveLevel = 0;
this._preserveWhitespace = 0;
this._preserveAll = false;
this._collect = false;
this._parser = undefined;
// Set input stream encoding and create an iconv instance,
// if conversion is required. Default working encoding is UTF-8,
// so iconv is used when input is anything else, but UTF-8.
this._encoding = encoding || null;
this._encoder = makeEncoder(this._encoding);
var scope = this;
// Start parsing.
process.nextTick(function () {
parse.call(scope);
});
}n/a
function FiniteAutomata() {
this._symbols = {};
this._states = {};
this._deterministic = true;
this._state = {};
this._callbacks = {
enter: {},
leave: {},
state: {},
flag: {}
};
this._stack = [];
this._stackPtr = -1;
}n/a
function EventEmitter() {
EventEmitter.init.call(this);
}n/a
function XmlStream(stream, encoding) {
events.EventEmitter.call(this);
this._stream = stream;
this._fa = new FiniteAutomata();
this._lastState = 0;
this._startState = {};
this._finalStates = {};
this._emitData = false;
this._bufferLevel = 0;
this._preserveLevel = 0;
this._preserveWhitespace = 0;
this._preserveAll = false;
this._collect = false;
this._parser = undefined;
// Set input stream encoding and create an iconv instance,
// if conversion is required. Default working encoding is UTF-8,
// so iconv is used when input is anything else, but UTF-8.
this._encoding = encoding || null;
this._encoder = makeEncoder(this._encoding);
var scope = this;
// Start parsing.
process.nextTick(function () {
parse.call(scope);
});
}n/a
function FiniteAutomata() {
this._symbols = {};
this._states = {};
this._deterministic = true;
this._state = {};
this._callbacks = {
enter: {},
leave: {},
state: {},
flag: {}
};
this._stack = [];
this._stackPtr = -1;
}n/a
enter = function (symbol, args) {
if (args == null) {
args = [];
}
var next = this.nextState(symbol);
this._stack[++this._stackPtr] = next;
this._state = next;
run.call(this, 'flag');
run.call(this, 'enter', args);
return this;
}n/a
go = function (symbol, args) {
var next = this.nextState(symbol)
this.setState(next, args);
return this;
}n/a
isDeterministic = function () {
return this._deterministic;
}n/a
leave = function (args) {
this._stack[this._stackPtr] = undefined;
run.call(this, 'leave', args);
this._state = this._stack[--this._stackPtr];
return this;
}n/a
nextState = function (symbol) {
var newState = {};
for (var st in this._state) if (__own.call(this._state, st)) {
if (__own.call(this._states, st)) {
var next = this._states[st];
if (__own.call(next, symbol)) {
extend(newState, next[symbol]);
}
if (__own.call(next, '')) {
extend(newState, (next['']));
}
}
}
return newState;
}...
}
}
}
return newState;
};
FiniteAutomata.prototype.go = function(symbol, args) {
var next = this.nextState(symbol)
this.setState(next, args);
return this;
};
FiniteAutomata.prototype.leave = function(args) {
this._stack[this._stackPtr] = undefined;
run.call(this, 'leave', args);
...on = function (type, state, cb) {
if (!__own.call(this._callbacks, type)) {
this._callbacks[type] = {};
}
var typeCbs = this._callbacks[type];
if (!__own.call(typeCbs, state)) {
typeCbs[state] = [];
}
typeCbs[state].push(cb);
return this;
}...
By default, parsed element node contains children as properties. In the case
of several children with same names, the last one would overwrite others.
To collect all of *subitem* elements in an array use **collect**:
```javascript
xml.collect('subitem');
xml.on('endElement: item', function(item) {
console.log(item);
})
```
# Preserving Elements and Text
By default, element text is returned as one concatenated string. In this XML:
...run = function (state, args) {
run.call(this, state, args);
}n/a
setState = function (state, args) {
this._state = state;
run.call(this, 'enter', args);
run.call(this, 'state', args);
return this;
}...
}
}
return newState;
};
FiniteAutomata.prototype.go = function(symbol, args) {
var next = this.nextState(symbol)
this.setState(next, args);
return this;
};
FiniteAutomata.prototype.leave = function(args) {
this._stack[this._stackPtr] = undefined;
run.call(this, 'leave', args);
this._state = this._stack[--this._stackPtr];
...transition = function (stateFrom, symbol, stateTo) {
this._symbols[symbol] = true;
var s;
if (__own.call(this._states, stateFrom)) {
s = this._states[stateFrom];
} else {
s = this._states[stateFrom] = {};
}
var exists = __own.call(s, symbol);
if (exists) {
s = s[symbol];
} else {
s = s[symbol] = {};
}
if (!__own.call(s, stateTo)) {
s[stateTo] = true;
this._deterministic &= !exists;
}
return this;
}n/a
function XmlStream(stream, encoding) {
events.EventEmitter.call(this);
this._stream = stream;
this._fa = new FiniteAutomata();
this._lastState = 0;
this._startState = {};
this._finalStates = {};
this._emitData = false;
this._bufferLevel = 0;
this._preserveLevel = 0;
this._preserveWhitespace = 0;
this._preserveAll = false;
this._collect = false;
this._parser = undefined;
// Set input stream encoding and create an iconv instance,
// if conversion is required. Default working encoding is UTF-8,
// so iconv is used when input is anything else, but UTF-8.
this._encoding = encoding || null;
this._encoder = makeEncoder(this._encoding);
var scope = this;
// Start parsing.
process.nextTick(function () {
parse.call(scope);
});
}n/a
function EventEmitter() {
EventEmitter.init.call(this);
}n/a
collect = function (selector) {
selector = normalizeSelector(selector);
var finalState = getFinalState.call(this, selector);
var self = this;
this._fa.on('flag', finalState, function() {
self._collect = true;
});
}...
```
By default, parsed element node contains children as properties. In the case
of several children with same names, the last one would overwrite others.
To collect all of *subitem* elements in an array use **collect**:
```javascript
xml.collect('subitem');
xml.on('endElement: item', function(item) {
console.log(item);
})
```
# Preserving Elements and Text
...on = function (eventName, listener) {
var event = parseEvent(eventName);
if (event !== null) {
// If we're dealing with a selector event,
// continue with selector-specific processing logic.
XmlStream.super_.prototype.on.call(this, event.name, listener);
var finalState = getFinalState.call(this, event.selector);
var self = this;
if (event.type === 'updateElement') {
this._fa.on('enter', finalState, function() {
self._bufferLevel++;
});
this._fa.on('leave', finalState, function(element, context, trace) {
self.emit(event.name, element, context, trace);
if (!--self._bufferLevel && self._emitData) {
emitElement.call(self, element, self._name, true);
}
});
} else {
var fn = function(element, context, trace) {
self.emit(event.name, element, context, trace);
};
this._fa.on(faModes[event.type], finalState, fn);
}
} else {
// Otherwise, we're dealing with a non-selector event.
if (eventName === 'data') {
this._emitData = true;
}
XmlStream.super_.prototype.on.call(this, eventName, listener);
}
}...
By default, parsed element node contains children as properties. In the case
of several children with same names, the last one would overwrite others.
To collect all of *subitem* elements in an array use **collect**:
```javascript
xml.collect('subitem');
xml.on('endElement: item', function(item) {
console.log(item);
})
```
# Preserving Elements and Text
By default, element text is returned as one concatenated string. In this XML:
...pause = function () {
this._stream.pause();
this._suspended = true;
if( !this._parser.pause() ) {
throw(new Error("Cannot pause parser: "+this._parser.getError()));
}
}...
```
# Pause and resume parsing
If you want parsing to pause (for example, until some asynchronous operation
of yours is finished), you can pause and resume XML parsing:
```javascript
xml.pause();
myAsyncFunction( function() {
xml.resume();
});
```
Beware that resume() **must not** be called from within a handler callback.
...preserve = function (selector, whitespace) {
selector = normalizeSelector(selector);
var finalState = getFinalState.call(this, selector);
var self = this;
this._fa.on('enter', finalState, function() {
self._preserveLevel++;
if (whitespace) {
self._preserveWhitespace++;
}
});
this._fa.on('leave', finalState, function() {
self._preserveLevel--;
if (whitespace) {
self._preserveWhitespace--;
}
});
}...
```
The value of **$text** for *item* would be: `one 1 two 2` without any
indication of the order of element *a*, element *b*, and text parts.
To preserve this order:
```javascript
xml.preserve('item');
xml.on('endElement: item', function(item) {
console.log(item);
})
```
# Pause and resume parsing
...resume = function () {
this._suspended = false;
if( !this._parser.resume() ) {
throw(new Error("Cannot resume parser: "+this._parser.getError()));
}
// resume stream only if parser hasn't been paused again
if( !this._suspended ) {
this._stream.resume();
}
}...
# Pause and resume parsing
If you want parsing to pause (for example, until some asynchronous operation
of yours is finished), you can pause and resume XML parsing:
```javascript
xml.pause();
myAsyncFunction( function() {
xml.resume();
});
```
Beware that resume() **must not** be called from within a handler callback.
...