Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
5e80d61428
commit
19018fc29e
235
js/dos/test/file1.dat
Normal file
235
js/dos/test/file1.dat
Normal file
|
@ -0,0 +1,235 @@
|
|||
(function () {
|
||||
|
||||
var sax;
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
// We're being used in a Node-like environment
|
||||
sax = require('sax');
|
||||
}
|
||||
else {
|
||||
// assume it's attached to the Window object in a browser
|
||||
sax = this.sax;
|
||||
|
||||
if (!sax) // no sax for you!
|
||||
throw new Error("Expected sax to be defined. Make sure you're including sax.js before this file.");
|
||||
}
|
||||
|
||||
/*
|
||||
XmlElement is our basic building block. Everything is an XmlElement; even XmlDocument
|
||||
behaves like an XmlElement by inheriting its attributes and functions.
|
||||
*/
|
||||
|
||||
function XmlElement(tag) {
|
||||
// Capture the parser object off of the XmlDocument delegate
|
||||
var parser = delegates[delegates.length - 1].parser;
|
||||
|
||||
this.name = tag.name;
|
||||
this.attr = tag.attributes || {};
|
||||
this.val = "";
|
||||
this.children = [];
|
||||
this.firstChild = null;
|
||||
this.lastChild = null;
|
||||
|
||||
// Assign parse information
|
||||
this.line = parser.line;
|
||||
this.column = parser.column;
|
||||
this.position = parser.position;
|
||||
this.startTagPosition = parser.startTagPosition;
|
||||
}
|
||||
|
||||
// SaxParser handlers
|
||||
|
||||
XmlElement.prototype._opentag = function(tag) {
|
||||
|
||||
var child = new XmlElement(tag);
|
||||
|
||||
// add to our children array
|
||||
this.children.push(child);
|
||||
|
||||
// update first/last pointers
|
||||
if (!this.firstChild) this.firstChild = child;
|
||||
this.lastChild = child;
|
||||
|
||||
delegates.unshift(child);
|
||||
};
|
||||
|
||||
XmlElement.prototype._closetag = function() {
|
||||
delegates.shift();
|
||||
};
|
||||
|
||||
XmlElement.prototype._text = function(text) {
|
||||
if (text) this.val += text;
|
||||
};
|
||||
|
||||
XmlElement.prototype._cdata = function(cdata) {
|
||||
if (cdata) this.val += cdata;
|
||||
};
|
||||
|
||||
// Useful functions
|
||||
|
||||
XmlElement.prototype.eachChild = function(iterator, context) {
|
||||
for (var i=0, l=this.children.length; i<l; i++)
|
||||
if (iterator.call(context, this.children[i], i, this.children) === false) return;
|
||||
};
|
||||
|
||||
XmlElement.prototype.childNamed = function(name) {
|
||||
for (var i=0, l=this.children.length; i<l; i++) {
|
||||
var child = this.children[i];
|
||||
if (child.name === name) return child;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
XmlElement.prototype.childrenNamed = function(name) {
|
||||
var matches = [];
|
||||
|
||||
for (var i=0, l=this.children.length; i<l; i++)
|
||||
if (this.children[i].name === name)
|
||||
matches.push(this.children[i]);
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
XmlElement.prototype.childWithAttribute = function(name,value) {
|
||||
for (var i=0, l=this.children.length; i<l; i++) {
|
||||
var child = this.children[i];
|
||||
if ( (value && child.attr[name] === value) || (!value && child.attr[name]) )
|
||||
return child;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
XmlElement.prototype.descendantWithPath = function(path) {
|
||||
var descendant = this;
|
||||
var components = path.split('.');
|
||||
|
||||
for (var i=0, l=components.length; i<l; i++)
|
||||
if (descendant)
|
||||
descendant = descendant.childNamed(components[i]);
|
||||
else
|
||||
return undefined;
|
||||
|
||||
return descendant;
|
||||
};
|
||||
|
||||
XmlElement.prototype.valueWithPath = function(path) {
|
||||
var components = path.split('@');
|
||||
var descendant = this.descendantWithPath(components[0]);
|
||||
if (descendant)
|
||||
return components.length > 1 ? descendant.attr[components[1]] : descendant.val;
|
||||
else
|
||||
return null;
|
||||
};
|
||||
|
||||
// String formatting (for debugging)
|
||||
|
||||
XmlElement.prototype.toString = function(options) {
|
||||
return this.toStringWithIndent("", options);
|
||||
};
|
||||
|
||||
XmlElement.prototype.toStringWithIndent = function(indent, options) {
|
||||
var s = indent + "<" + this.name;
|
||||
var linebreak = options && options.compressed ? "" : "\n";
|
||||
|
||||
for (var name in this.attr)
|
||||
if (Object.prototype.hasOwnProperty.call(this.attr, name))
|
||||
s += " " + name + '="' + this.attr[name] + '"';
|
||||
|
||||
var finalVal = this.val.trim().replace(/</g, "<").replace(/>/g, ">").replace(/&/g, '&');
|
||||
|
||||
if (options && options.trimmed && finalVal.length > 25)
|
||||
finalVal = finalVal.substring(0,25).trim() + "…";
|
||||
|
||||
if (this.children.length) {
|
||||
s += ">" + linebreak;
|
||||
|
||||
var childIndent = indent + (options && options.compressed ? "" : " ");
|
||||
|
||||
if (finalVal.length)
|
||||
s += childIndent + finalVal + linebreak;
|
||||
|
||||
for (var i=0, l=this.children.length; i<l; i++)
|
||||
s += this.children[i].toStringWithIndent(childIndent, options) + linebreak;
|
||||
|
||||
s += indent + "</" + this.name + ">";
|
||||
}
|
||||
else if (finalVal.length) {
|
||||
s += ">" + finalVal + "</" + this.name +">";
|
||||
}
|
||||
else s += "/>";
|
||||
|
||||
return s;
|
||||
};
|
||||
|
||||
/*
|
||||
XmlDocument is the class we expose to the user; it uses the sax parser to create a hierarchy
|
||||
of XmlElements.
|
||||
*/
|
||||
|
||||
function XmlDocument(xml) {
|
||||
xml && (xml = xml.toString().trim());
|
||||
|
||||
if (!xml)
|
||||
throw new Error("No XML to parse!");
|
||||
|
||||
// Expose the parser to the other delegates while the parser is running
|
||||
this.parser = sax.parser(true); // strict
|
||||
addParserEvents(this.parser);
|
||||
|
||||
// We'll use the file-scoped "delegates" var to remember what elements we're currently
|
||||
// parsing; they will push and pop off the stack as we get deeper into the XML hierarchy.
|
||||
// It's safe to use a global because JS is single-threaded.
|
||||
delegates = [this];
|
||||
|
||||
this.parser.write(xml);
|
||||
|
||||
// Remove the parser as it is no longer needed and should not be exposed to clients
|
||||
delete this.parser;
|
||||
}
|
||||
|
||||
// make XmlDocument inherit XmlElement's methods
|
||||
extend(XmlDocument.prototype, XmlElement.prototype);
|
||||
|
||||
XmlDocument.prototype._opentag = function(tag) {
|
||||
if (typeof this.children === 'undefined')
|
||||
// the first tag we encounter should be the root - we'll "become" the root XmlElement
|
||||
XmlElement.call(this,tag);
|
||||
else
|
||||
// all other tags will be the root element's children
|
||||
XmlElement.prototype._opentag.apply(this,arguments);
|
||||
};
|
||||
|
||||
// file-scoped global stack of delegates
|
||||
var delegates = null;
|
||||
|
||||
/*
|
||||
Helper functions
|
||||
*/
|
||||
|
||||
function addParserEvents(parser) {
|
||||
parser.onopentag = parser_opentag;
|
||||
parser.onclosetag = parser_closetag;
|
||||
parser.ontext = parser_text;
|
||||
parser.oncdata = parser_cdata;
|
||||
}
|
||||
|
||||
// create these closures and cache them by keeping them file-scoped
|
||||
function parser_opentag() { delegates[0]._opentag.apply(delegates[0],arguments) }
|
||||
function parser_closetag() { delegates[0]._closetag.apply(delegates[0],arguments) }
|
||||
function parser_text() { delegates[0]._text.apply(delegates[0],arguments) }
|
||||
function parser_cdata() { delegates[0]._cdata.apply(delegates[0],arguments) }
|
||||
|
||||
// a relatively standard extend method
|
||||
function extend(destination, source) {
|
||||
for (var prop in source)
|
||||
if (source.hasOwnProperty(prop))
|
||||
destination[prop] = source[prop];
|
||||
}
|
||||
|
||||
// Are we being used in a Node-like environment?
|
||||
if (typeof module !== 'undefined' && module.exports)
|
||||
module.exports.XmlDocument = XmlDocument;
|
||||
else
|
||||
this.XmlDocument = XmlDocument;
|
||||
|
||||
})();
|
Loading…
Reference in New Issue
Block a user