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.
...