-
Notifications
You must be signed in to change notification settings - Fork 18
/
domparser.js
126 lines (109 loc) · 3.65 KB
/
domparser.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
* Constructs a function which installs SAX handlers into a libxmljs.SaxParser
* turning it into a DOM parser for the given doc.
*
* The function returned by this function will typically be used as the
* argument of lixmljs.SaxParser Constructor.
* <code>
* var dom = require("jsdom").level(3, 'core'),
* xml = require("libxmljs"),
* domparser = require("./domparser.js");
*
* var doc = new dom.Document();
* var parser = new xml.SaxParser(domparser.handlersForDocument(doc));
* parser.parseFile('example.xml');
* // doc is now populated with the contents of example.xml file
* </code>
*
* @param doc A document instance implementing at least DOM Core Level 2.
* @returns An object suitable for passing to the libxmljs.SaxParser and
* libixmljs.PushParser constructors.
*/
exports.handlersForDocument = function(doc) {
/** @private */
var currentElement = doc;
/** @private */
var currentCharacters = '';
/** @private */
var currentCdata = '';
/**
* Add text node or CDATA section before starting or ending an element
*/
function flushData() {
if (currentCharacters) {
currentElement.appendChild(
doc.createTextNode(currentCharacters));
currentCharacters = '';
}
else if (currentCdata) {
currentElement.appendChild(
doc.createCDATASection(currentCdata));
currentCdata = '';
}
}
return {
startDocument: function() {},
endDocument: function() {},
startElementNS: function(elem, attrs, prefix, uri, namespaces) {
var element;
// Finish preceeding text node or CDATA section if any.
flushData();
// Create element
if (uri) {
if (prefix) {
element = doc.createElementNS(uri, prefix + ':' + elem);
}
else {
element = doc.createElementNS(uri, elem);
}
}
else {
element = doc.createElementNS(null, elem);
}
// Add attributes
attrs.forEach(function(inattr) {
var attrLocalName = inattr[0];
var attrPrefix = inattr[1];
var attrUri = inattr[2];
var attrValue = inattr[3];
if (attrPrefix) {
element.setAttributeNS(attrUri,
attrPrefix + ':' + attrLocalName, attrValue);
}
else {
element.setAttribute(attrLocalName, attrValue);
}
});
// Add namespace attributes. Default namespace has prefix=='',
// ignore it.
namespaces.forEach(function(ns) {
if (ns[0]) {
element.setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:' + ns[0], ns[1]);
}
});
currentElement.appendChild(element);
currentElement = element;
},
endElementNS: function(elem, prefix, uri) {
flushData();
currentElement = currentElement.parentNode;
},
characters: function(chars) {
currentCharacters += chars;
},
cdata: function(cdata) {
currentCdata += cdata;
},
comment: function(comment) {
currentElement.appendChild(doc.createComment(comment));
},
warning: function(msg) {
// FIXME
},
error: function(msg) {
// FIXME
}
};
};