Skip to content

Commit 24bb1be

Browse files
committed
Simplify parsing logic into separate parsers
Remove fields from model that are rarely used
1 parent af5339e commit 24bb1be

File tree

9 files changed

+365
-227
lines changed

9 files changed

+365
-227
lines changed

docs/rss-specifications.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@
3737
| categories | category | category |
3838
| authors | author | contributor |
3939
| published | pubDate | published |
40-
40+
| enclosures | enclosures |

index.js

Lines changed: 16 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,38 @@
11
var DOMParser = require('xmldom').DOMParser;
2-
var fields = require('./model/fields');
3-
var types = require('./model/types');
2+
var rssV2Parser = require('./parsers/rssv2');
3+
var atomV1Parser = require('./parsers/atomv1');
44

55
exports.parse = function(feed) {
66
return new Promise((resolve, reject) => {
7-
var parsedFeed = {};
87
var document = new DOMParser({
98
errorHandler: function(level, msg) {
109
reject(msg);
1110
}
1211
}).parseFromString(feed, 'text/xml');
1312

14-
let channel = document.getElementsByTagName('channel')[0];
15-
let feedElement = document.getElementsByTagName('feed')[0];
13+
let parser = getParser(document);
1614

17-
if (channel) {
18-
parsedFeed = parseFields(channel, fields.rssv2);
19-
resolve(parsedFeed);
20-
} else if (feedElement) {
21-
parsedFeed = parseFields(feedElement, fields.atomv1);
22-
resolve(parsedFeed);
23-
} else {
15+
if (!parser) {
2416
reject('Unable to find any RSS element in feed');
2517
}
26-
});
27-
};
28-
29-
function parseFields(node, fields) {
30-
const parsedNode = {};
18+
19+
let parsedFeed = parser.parse(document);
3120

32-
Object.keys(fields).forEach(function(key) {
33-
const field = fields[key];
34-
const parsedFieldKey = field.fieldOverride || key;
35-
36-
if (field.type === types.object) {
37-
if (field.attribute) {
38-
parsedNode[parsedFieldKey] = getElementAttributeContent(node, key, field.attribute);
39-
} else if (field.attributes) {
40-
parsedNode[parsedFieldKey] = {};
41-
Object.keys(field.attributes).forEach(function(attribute) {
42-
parsedNode[parsedFieldKey][attribute] = getElementAttributeContent(node, key, attribute);
43-
});
44-
} else {
45-
parsedNode[parsedFieldKey] = getElementTextContent(node, key);
46-
}
47-
} else if (field.type === types.array) {
48-
parsedNode[parsedFieldKey] = [];
49-
const elements = getChildElements(node, key);
50-
51-
Array.prototype.forEach.call(elements, element => {
52-
let arrayNode = {};
53-
54-
if (field.elements) {
55-
arrayNode = parseFields(element, field.elements);
56-
} else if (element.textContent) {
57-
arrayNode.value = element.textContent;
58-
}
59-
60-
if (field.attributes) {
61-
Object.keys(field.attributes).forEach(function(attribute) {
62-
arrayNode[attribute] = getElementAttributeContent(node, key, attribute);
63-
});
64-
}
65-
66-
parsedNode[parsedFieldKey].push(arrayNode);
67-
});
68-
}
21+
resolve(parsedFeed);
6922
});
23+
};
7024

71-
return parsedNode;
72-
}
73-
74-
function getChildElements(node, tagName) {
75-
if (!node || !node.getElementsByTagName(tagName)) {
76-
return [];
77-
}
78-
79-
let elements = node.getElementsByTagName(tagName);
80-
81-
return Array.prototype.filter.call(elements, element =>
82-
element.parentNode.nodeName === node.nodeName);
83-
}
84-
85-
function getElementTextContent(node, tagName) {
86-
const nodes = getChildElements(node, tagName);
25+
function getParser(document) {
26+
let isRssSpecification = document.getElementsByTagName('channel')[0] !== undefined;
27+
let isAtomSpecification = document.getElementsByTagName('feed')[0] !== undefined;
8728

88-
if (!nodes || nodes.length === 0) {
89-
return undefined;
29+
if (isRssSpecification) {
30+
return rssV2Parser;
9031
}
9132

92-
return nodes[0].textContent;
93-
}
94-
95-
function getElementAttributeContent(node, tagName, attribute) {
96-
const nodes = getChildElements(node, tagName);
97-
98-
if (!nodes || nodes.length === 0) {
99-
return undefined;
33+
if (isAtomSpecification) {
34+
return atomV1Parser;
10035
}
10136

102-
return nodes[0].getAttribute(attribute);
37+
return;
10338
}

model/fields.js

Lines changed: 0 additions & 107 deletions
This file was deleted.

model/rss.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
const model = module.exports = {};
2+
3+
model.rss = {
4+
type: undefined,
5+
title: undefined,
6+
link: undefined,
7+
description: undefined,
8+
language: undefined,
9+
copyright: undefined,
10+
authors: [{
11+
name: undefined
12+
}],
13+
lastUpdated: undefined,
14+
lastPublished: undefined,
15+
categories: [{
16+
name: undefined
17+
}],
18+
image: {
19+
url: undefined,
20+
title: undefined,
21+
description: undefined,
22+
width: undefined,
23+
height: undefined
24+
},
25+
items: [{
26+
title: undefined,
27+
link: undefined,
28+
description: undefined,
29+
content: undefined,
30+
categories: [{
31+
name: undefined
32+
}],
33+
authors: [{
34+
name: undefined
35+
}],
36+
published: undefined,
37+
enclosures: [{
38+
url: undefined,
39+
length: undefined,
40+
mimeType: undefined
41+
}]
42+
}]
43+
};
44+
45+
// 'title': { type: types.object },
46+
// 'link': { type: types.object },
47+
// 'description': { type: types.object },
48+
// 'language': { type: types.object },
49+
// 'copyright': { type: types.object },
50+
// 'managingEditor': { type: types.object },
51+
// 'webMaster': { type: types.object },
52+
// 'pubDate': { type: types.object },
53+
// 'lastBuildDate': { type: types.object },
54+
// 'category': {
55+
// type: types.array,
56+
// fieldOverride: 'categories'
57+
// },
58+
// 'generator': { type: types.object },
59+
// 'ttl': { type: types.object },
60+
// 'image': { type: types.object },
61+
// 'skipHours': { type: types.object },
62+
// 'skipDays': { type: types.object },
63+
// 'image': {
64+
// type: types.object,
65+
// attributes: {
66+
// 'url': { type: types.object },
67+
// 'title': { type: types.object },
68+
// 'link': { type: types.object },
69+
// 'width': { type: types.object },
70+
// 'height': { type: types.object },
71+
// 'description': { type: types.object }
72+
// }
73+
// },
74+
// 'item': {
75+
// type: types.array,
76+
// fieldOverride: 'items',
77+
// elements: {
78+
// 'title': { type: types.object },
79+
// 'link': { type: types.object },
80+
// 'description': { type: types.object },
81+
// 'author': {
82+
// type: types.array,
83+
// fieldOverride: 'authors'
84+
// },
85+
// 'category': {
86+
// type: types.array,
87+
// fieldOverride: 'categories'
88+
// },
89+
// 'comments': {
90+
// type: types.array,
91+
// fieldOverride: 'comments'
92+
// },
93+
// 'enclosure': {
94+
// type: types.array,
95+
// fieldOverride: 'enclosures',
96+
// attributes: {
97+
// 'url': { type: types.object },
98+
// 'length': { type: types.object },
99+
// 'type': { type: types.object }
100+
// }
101+
// },
102+
// 'guid': {
103+
// type: types.array,
104+
// fieldOverride: 'guids'
105+
// },
106+
// 'pubDate': { type: types.object },
107+
// 'source': {
108+
// type: types.object,
109+
// attributes: {
110+
// 'url': { type: types.object }
111+
// }
112+
// }
113+
// }
114+
// }

model/types.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

parsers/atomv1.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var utils = require('./utils');
2+
3+
exports.parse = function(document) {
4+
5+
};

0 commit comments

Comments
 (0)