Reputation: 136
I've been going round and round with this Javascript problem for four days and have finally managed to get it working. But I feel sure there must be a much better solution, one involving fewer 'translations', something that puts less strain on the browser.
I feel I should be able to read the xml of the feed, do a little re-mapping of tags in the inbound feed into tags in the outbound one. Can I? Do I have to stick with the solution I've got working:
In a nutshull, I'm taking via an http request an RSS feed that has some media tags. It 'arrives' as the xml of a dom structure that replicates the feed. I then have to reconstruct the feed items (with a little remapping) from that dom so they can be returned to the calling routine (via a global variable).
I've looked into all sorts of potential alternatives: jQuery.get, json and others but all examples I could find online seem to ignore the media items in the inbound feed - at least I couldn't find them when trying to read the feed.
This is an entry in the rss feed being used as the source:
<item>
<guid isPermaLink="false">https://www.zazzle.com/create_your_own_photostamp_by_stamps_com-172639479866885637?rf=238582202591969585&tc=_041218</guid>
<pubDate>Mon, 19 Nov 2018 23:49:28 GMT</pubDate>
<title>
<![CDATA[Create Your Own PhotoStamp by Stamps.com]]>
</title>
<link>https://www.zazzle.com/create_your_own_photostamp_by_stamps_com-172639479866885637?rf=238582202591969585&tc=_041218&pm=</link>
<author>
<name>zazzle_templates</name>
</author>
<description>
<![CDATA[]]>
</description>
<price>$myItem->price</price>
<media:title>
<![CDATA[Create Your Own PhotoStamp by Stamps.com]]>
</media:title>
<media:description>
<![CDATA[Upload your own photo or design to create your set of custom photo postage stamps by Stamps.com!]]>
</media:description>
<media:price>$22.95</media:price>
<media:thumbnail url="https://rlv.zcache.com/create_your_own_photostamp_by_stamps_com-r0453bb627c114b9da57442d3dd284e6a_byxt0_8byvr_152.jpg" />
<media:content url="https://rlv.zcache.com/create_your_own_photostamp_by_stamps_com-r0453bb627c114b9da57442d3dd284e6a_byxt0_8byvr_500.jpg" />
<media:keywords>
<![CDATA[create your own, upload your own, template, postage stamp, mailing stamp, wedding, save the date, anniversary, birthday, occasion]]>
</media:keywords>
<media:rating scheme="urn:mpaa">g</media:rating>
</item>
This is the code I'm using (no, I'm not a coder. I mostly code by recognising patterns in examples and understanding equivalence of one thing with another)
(function ($) {
'use strict';
$.fn.rssfeed = function (url, options, fn) {
return this.each(function (i, e) {
if (!$(e).hasClass('rssFeed')) { $(e).addClass('rssFeed'); }
if (url === null) { return false; }
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
process(this);
if ($.isFunction(fn)) { fn.call(this, $(e)); } }
};
xmlhttp.open("GET", url , true);
xmlhttp.send();
});
};
var process = function (xml) {
var i, xmlDoc, table;
xmlDoc = xml.responseXML;
var myItemAsAnObject = [];
feedLength = xmlDoc.getElementsByTagName("item").length;
console.log("feed length: " + feedLength);
if (feedLength == 0) { return false; }
var x = xmlDoc.getElementsByTagName("item");
for (var i = 0; i < x.length; i++) {
myItemAsAnObject[i] = {
pubDate: x[i].getElementsByTagName("pubDate")[0].firstChild.nodeValue,
link: x[i].getElementsByTagName("link")[0].firstChild.nodeValue,
keywords: x[i].getElementsByTagName("media:keywords")[0].childNodes[0].data,
author: {name: x[i].getElementsByTagName("author")[0].childNodes[0].childNodes[0].nodeValue},
content: {url: x[i].getElementsByTagName("media:content")[0].attributes[0].nodeValue},
description: [
x[i].getElementsByTagName("description")[0].childNodes[0].data,
x[i].getElementsByTagName("media:description")[0].childNodes[0].data
],
guid: {isPermaLink: "false", content: x[i].getElementsByTagName("guid")[0].childNodes[0].nodeValue},
price: [
"$myItem->price",
x[i].getElementsByTagName("media:price")[0].firstChild.nodeValue
],
thumbnail: {url: x[i].getElementsByTagName("media:thumbnail")[0].attributes[0].nodeValue},
rating: {
scheme: x[i].getElementsByTagName("media:rating")[0].attributes[0].nodeValue,
content: x[i].getElementsByTagName("media:rating")[0].childNodes[0].nodeValue
},
title: [
x[i].getElementsByTagName("title")[0].firstChild.nodeValue,
x[i].getElementsByTagName("media:title")[0].childNodes[0].data
]
};
}
feedContent = myItemAsAnObject;
};
})(jQuery);
Upvotes: 0
Views: 139
Reputation: 42267
Well, the parsing is actually pretty easy if you're only doing it in a browser. The following won't directly work in node but you could use js-dom (but honestly there's better xml parsers you should use in that case.)
https://codepen.io/anon/pen/yQdjyo?editors=0010
const rss = `
<item>
<guid isPermaLink="false">https://www.zazzle.com/create_your_own_photostamp_by_stamps_com-172639479866885637?rf=238582202591969585&tc=_041218</guid>
<pubDate>Mon, 19 Nov 2018 23:49:28 GMT</pubDate>
<title>
<![CDATA[Create Your Own PhotoStamp by Stamps.com]]>
</title>
<link>https://www.zazzle.com/create_your_own_photostamp_by_stamps_com-172639479866885637?rf=238582202591969585&tc=_041218&pm=</link>
<author>
<name>zazzle_templates</name>
</author>
<description>
<![CDATA[]]>
</description>
<price>$myItem->price</price>
<media:title>
<![CDATA[Create Your Own PhotoStamp by Stamps.com]]>
</media:title>
<media:description>
<![CDATA[Upload your own photo or design to create your set of custom photo postage stamps by Stamps.com!]]>
</media:description>
<media:price>$22.95</media:price>
<media:thumbnail url="https://rlv.zcache.com/create_your_own_photostamp_by_stamps_com-r0453bb627c114b9da57442d3dd284e6a_byxt0_8byvr_152.jpg" />
<media:content url="https://rlv.zcache.com/create_your_own_photostamp_by_stamps_com-r0453bb627c114b9da57442d3dd284e6a_byxt0_8byvr_500.jpg" />
<media:keywords>
<![CDATA[create your own, upload your own, template, postage stamp, mailing stamp, wedding, save the date, anniversary, birthday, occasion]]>
</media:keywords>
<media:rating scheme="urn:mpaa">g</media:rating>
</item>
`;
const doc = document.createDocumentFragment();
const root = document.createElement('div');
root.innerHTML = rss;
doc.appendChild(root);
// const getValue = (selector) => root.querySelectorAll(selector).innerHTML;
// const obj = {
// pubDate: getValue('pubDate'),
// link: getValue('link'),
// keywords: getValue('media:keywords'),
// author: {name: ''},
// content: {url: ''},
// description: [
// ],
// guid: '',
// thumbnail: '',
// rating: {
// scheme: '',
// content: ''
// },
// title: [
// ]
// };
// console.log(obj);
This converts the xml string into a document fragment, and you can then run queries against it. querySelector
and querySelectorAll
work fine as long as the xml nodes don't contain :
. For example, <media:price>
isn't parseable by querySelector.
This should at least make part of your code simpler.
Upvotes: 1