PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/citeproc-js/src/xmldom.js

https://github.com/discoverygarden/ir_citation
JavaScript | 450 lines | 340 code | 36 blank | 74 comment | 115 complexity | 8af9256b8742465ba7f2e4356977ae44 MD5 | raw file
  1. /*
  2. * Copyright (c) 2009, 2010 and 2011 Frank G. Bennett, Jr. All Rights
  3. * Reserved.
  4. *
  5. * The contents of this file are subject to the Common Public
  6. * Attribution License Version 1.0 (the “License”); you may not use
  7. * this file except in compliance with the License. You may obtain a
  8. * copy of the License at:
  9. *
  10. * http://bitbucket.org/fbennett/citeproc-js/src/tip/LICENSE.
  11. *
  12. * The License is based on the Mozilla Public License Version 1.1 but
  13. * Sections 14 and 15 have been added to cover use of software over a
  14. * computer network and provide for limited attribution for the
  15. * Original Developer. In addition, Exhibit A has been modified to be
  16. * consistent with Exhibit B.
  17. *
  18. * Software distributed under the License is distributed on an “AS IS”
  19. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  20. * the License for the specific language governing rights and limitations
  21. * under the License.
  22. *
  23. * The Original Code is the citation formatting software known as
  24. * "citeproc-js" (an implementation of the Citation Style Language
  25. * [CSL]), including the original test fixtures and software located
  26. * under the ./std subdirectory of the distribution archive.
  27. *
  28. * The Original Developer is not the Initial Developer and is
  29. * __________. If left blank, the Original Developer is the Initial
  30. * Developer.
  31. *
  32. * The Initial Developer of the Original Code is Frank G. Bennett,
  33. * Jr. All portions of the code written by Frank G. Bennett, Jr. are
  34. * Copyright (c) 2009 and 2010 Frank G. Bennett, Jr. All Rights Reserved.
  35. *
  36. * Alternatively, the contents of this file may be used under the
  37. * terms of the GNU Affero General Public License (the [AGPLv3]
  38. * License), in which case the provisions of [AGPLv3] License are
  39. * applicable instead of those above. If you wish to allow use of your
  40. * version of this file only under the terms of the [AGPLv3] License
  41. * and not to allow others to use your version of this file under the
  42. * CPAL, indicate your decision by deleting the provisions above and
  43. * replace them with the notice and other provisions required by the
  44. * [AGPLv3] License. If you do not delete the provisions above, a
  45. * recipient may use your version of this file under either the CPAL
  46. * or the [AGPLv3] License.”
  47. */
  48. /**
  49. * Functions for parsing an XML object using E4X.
  50. */
  51. var ActiveXObject;
  52. var XMLHttpRequest;
  53. var DOMParser;
  54. var CSL_IS_IE;
  55. var CSL_CHROME = function () {
  56. if ("undefined" == typeof DOMParser || CSL_IS_IE) {
  57. CSL_IS_IE = true;
  58. DOMParser = function() {};
  59. DOMParser.prototype.parseFromString = function(str, contentType) {
  60. if ("undefined" != typeof ActiveXObject) {
  61. var xmldata = new ActiveXObject('MSXML.DomDocument');
  62. xmldata.async = false;
  63. xmldata.loadXML(str);
  64. return xmldata;
  65. } else if ("undefined" != typeof XMLHttpRequest) {
  66. var xmldata = new XMLHttpRequest;
  67. if (!contentType) {
  68. contentType = 'text/xml';
  69. }
  70. xmldata.open('GET', 'data:' + contentType + ';charset=utf-8,' + encodeURIComponent(str), false);
  71. if(xmldata.overrideMimeType) {
  72. xmldata.overrideMimeType(contentType);
  73. }
  74. xmldata.send(null);
  75. return xmldata.responseXML;
  76. }
  77. };
  78. this.hasAttributes = function (node) {
  79. var ret;
  80. if (node.attributes && node.attributes.length) {
  81. ret = true;
  82. } else {
  83. ret = false;
  84. }
  85. return ret;
  86. };
  87. } else {
  88. this.hasAttributes = function (node) {
  89. return node["hasAttributes"]();
  90. };
  91. }
  92. this.importNode = function (doc, srcElement) {
  93. if ("undefined" == typeof doc.importNode) {
  94. var ret = this._importNode(doc, srcElement, true);
  95. } else {
  96. var ret = doc.importNode(srcElement, true);
  97. }
  98. return ret;
  99. };
  100. // In case importNode is not available.
  101. // Thx + hat tip to Anthony T. Holdener III
  102. // http://www.alistapart.com/articles/crossbrowserscripting
  103. // cases 3, 4, 8 = text, cdata, comment
  104. this._importNode = function(doc, node, allChildren) {
  105. switch (node.nodeType) {
  106. // element node
  107. case 1:
  108. var newNode = doc.createElement(node.nodeName);
  109. if (node.attributes && node.attributes.length > 0)
  110. for (var i = 0, il = node.attributes.length; i < il;)
  111. newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i++].nodeName));
  112. if (allChildren && node.childNodes && node.childNodes.length > 0)
  113. for (var i = 0, il = node.childNodes.length; i < il;)
  114. newNode.appendChild(this._importNode(doc, node.childNodes[i++], allChildren));
  115. return newNode;
  116. break;
  117. case 3:
  118. case 4:
  119. case 8:
  120. // Drop comments on the floor as well.
  121. //return doc.createTextNode(node.nodeValue);
  122. //break;
  123. }
  124. };
  125. this.parser = new DOMParser();
  126. // This seems horribly tormented, but there might be a reason for it.
  127. // Perhaps this was the only way I found to get namespacing to work ... ?
  128. var str = "<docco><institution institution-parts=\"long\" delimiter=\", \" substitute-use-first=\"1\" use-last=\"1\"><institution-part name=\"long\"></institution></docco>";
  129. var inst_doc = this.parser.parseFromString(str, "text/xml");
  130. var inst_node = inst_doc.getElementsByTagName("institution");
  131. this.institution = inst_node.item(0);
  132. var inst_part_node = inst_doc.getElementsByTagName("institution-part");
  133. this.institutionpart = inst_part_node.item(0);
  134. this.ns = "http://purl.org/net/xbiblio/csl";
  135. };
  136. /**
  137. * No need for cleaning with the DOM, I think. This will probably just be a noop.
  138. * But first, let's get XML mode switching up and running.
  139. */
  140. CSL_CHROME.prototype.clean = function (xml) {
  141. xml = xml.replace(/<\?[^?]+\?>/g, "");
  142. xml = xml.replace(/<![^>]+>/g, "");
  143. xml = xml.replace(/^\s+/, "");
  144. xml = xml.replace(/\s+$/, "");
  145. xml = xml.replace(/^\n*/, "");
  146. return xml;
  147. };
  148. /**
  149. * Methods to call on a node.
  150. */
  151. CSL_CHROME.prototype.getStyleId = function (myxml) {
  152. var text = "";
  153. var node = myxml.getElementsByTagName("id");
  154. if (node && node.length) {
  155. node = node.item(0);
  156. }
  157. if (node) {
  158. // W3C conformant browsers
  159. text = node.textContent;
  160. }
  161. if (!text) {
  162. // Opera, IE 6 & 7
  163. text = node.innerText;
  164. }
  165. if (!text) {
  166. // Safari
  167. text = node.innerHTML;
  168. }
  169. return text;
  170. };
  171. CSL_CHROME.prototype.children = function (myxml) {
  172. var children, pos, len, ret;
  173. if (myxml) {
  174. ret = [];
  175. children = myxml.childNodes;
  176. for (pos = 0, len = children.length; pos < len; pos += 1) {
  177. if (children[pos].nodeName != "#text") {
  178. ret.push(children[pos]);
  179. }
  180. }
  181. return ret;
  182. } else {
  183. return [];
  184. }
  185. };
  186. CSL_CHROME.prototype.nodename = function (myxml) {
  187. var ret = myxml.nodeName;
  188. return ret;
  189. };
  190. CSL_CHROME.prototype.attributes = function (myxml) {
  191. var ret, attrs, attr, key, xml, pos, len;
  192. ret = new Object();
  193. if (myxml && this.hasAttributes(myxml)) {
  194. attrs = myxml.attributes;
  195. for (pos = 0, len=attrs.length; pos < len; pos += 1) {
  196. attr = attrs[pos];
  197. ret["@" + attr.name] = attr.value;
  198. }
  199. }
  200. return ret;
  201. };
  202. CSL_CHROME.prototype.content = function (myxml) {
  203. var ret;
  204. if ("undefined" != typeof myxml.textContent) {
  205. ret = myxml.textContent;
  206. } else if ("undefined" != typeof myxml.innerText) {
  207. ret = myxml.innerText;
  208. } else {
  209. ret = myxml.txt;
  210. }
  211. return ret;
  212. };
  213. CSL_CHROME.prototype.namespace = {
  214. "xml":"http://www.w3.org/XML/1998/namespace"
  215. }
  216. CSL_CHROME.prototype.numberofnodes = function (myxml) {
  217. if (myxml) {
  218. return myxml.length;
  219. } else {
  220. return 0;
  221. }
  222. };
  223. CSL_CHROME.prototype.getAttributeName = function (attr) {
  224. var ret = attr.name;
  225. return ret;
  226. }
  227. CSL_CHROME.prototype.getAttributeValue = function (myxml,name,namespace) {
  228. var ret = "";
  229. if (myxml && this.hasAttributes(myxml) && myxml.getAttribute(name)) {
  230. ret = myxml.getAttribute(name);
  231. }
  232. return ret;
  233. }
  234. //
  235. // Can't this be, you know ... simplified?
  236. //
  237. CSL_CHROME.prototype.getNodeValue = function (myxml,name) {
  238. var ret = "";
  239. if (name){
  240. var vals = myxml.getElementsByTagName(name);
  241. if (vals.length > 0) {
  242. if ("undefined" != typeof vals[0].textContent) {
  243. ret = vals[0].textContent;
  244. } else if ("undefined" != typeof vals[0].innerText) {
  245. ret = vals[0].innerText;
  246. } else {
  247. ret = vals[0].text;
  248. }
  249. }
  250. } else {
  251. ret = myxml;
  252. }
  253. if (ret && ret.childNodes && (ret.childNodes.length == 0 || (ret.childNodes.length == 1 && ret.firstChild.nodeName == "#text"))) {
  254. if ("undefined" != typeof ret.textContent) {
  255. ret = ret.textContent;
  256. } else if ("undefined" != typeof ret.innerText) {
  257. ret = ret.innerText;
  258. } else {
  259. ret = ret.text;
  260. }
  261. }
  262. return ret;
  263. }
  264. CSL_CHROME.prototype.setAttributeOnNodeIdentifiedByNameAttribute = function (myxml,nodename,partname,attrname,val) {
  265. var pos, len, xml, nodes, node;
  266. if (attrname.slice(0,1) === '@'){
  267. attrname = attrname.slice(1);
  268. }
  269. nodes = myxml.getElementsByTagName(nodename);
  270. for (pos = 0, len = nodes.length; pos < len; pos += 1) {
  271. node = nodes[pos];
  272. if (node.getAttribute("name") != partname) {
  273. continue;
  274. }
  275. node.setAttribute(attrname, val);
  276. }
  277. }
  278. CSL_CHROME.prototype.deleteNodeByNameAttribute = function (myxml,val) {
  279. var pos, len, node, nodes;
  280. nodes = myxml.childNodes;
  281. for (pos = 0, len = nodes.length; pos < len; pos += 1) {
  282. node = nodes[pos];
  283. if (!node || node.nodeType == node.TEXT_NODE) {
  284. continue;
  285. }
  286. if (this.hasAttributes(node) && node.getAttribute("name") == val) {
  287. myxml.removeChild(nodes[pos]);
  288. }
  289. }
  290. }
  291. CSL_CHROME.prototype.deleteAttribute = function (myxml,attr) {
  292. myxml.removeAttribute(attr);
  293. }
  294. CSL_CHROME.prototype.setAttribute = function (myxml,attr,val) {
  295. var attribute;
  296. if (!myxml.ownerDocument) {
  297. myxml = myxml.firstChild;
  298. }
  299. attribute = myxml.ownerDocument.createAttribute(attr);
  300. myxml.setAttribute(attr, val);
  301. return false;
  302. }
  303. CSL_CHROME.prototype.nodeCopy = function (myxml) {
  304. var cloned_node = myxml.cloneNode(true);
  305. return cloned_node;
  306. }
  307. CSL_CHROME.prototype.getNodesByName = function (myxml,name,nameattrval) {
  308. var ret, nodes, node, pos, len;
  309. ret = [];
  310. nodes = myxml.getElementsByTagName(name);
  311. for (pos = 0, len = nodes.length; pos < len; pos += 1) {
  312. node = nodes.item(pos);
  313. if (nameattrval && !(this.hasAttributes(node) && node.getAttribute("name") == nameattrval)) {
  314. // if (nameattrval && !(this.attributes && node.attributes.name && node.attributes.name.value == nameattrval)) {
  315. continue;
  316. }
  317. ret.push(node);
  318. }
  319. return ret;
  320. }
  321. CSL_CHROME.prototype.nodeNameIs = function (myxml,name) {
  322. if (name == myxml.nodeName) {
  323. return true;
  324. }
  325. return false;
  326. }
  327. CSL_CHROME.prototype.makeXml = function (myxml) {
  328. var ret, topnode;
  329. if (!myxml) {
  330. myxml = "<docco><bogus/></docco>";
  331. }
  332. myxml = myxml.replace(/\s*<\?[^>]*\?>\s*\n*/g, "");
  333. var nodetree = this.parser.parseFromString(myxml, "application/xml");
  334. return nodetree.firstChild;
  335. };
  336. CSL_CHROME.prototype.insertChildNodeAfter = function (parent,node,pos,datexml) {
  337. var myxml, xml;
  338. myxml = this.importNode(node.ownerDocument, datexml);
  339. parent.replaceChild(myxml, node);
  340. return parent;
  341. };
  342. CSL_CHROME.prototype.insertPublisherAndPlace = function(myxml) {
  343. var group = myxml.getElementsByTagName("group");
  344. for (var i = 0, ilen = group.length; i < ilen; i += 1) {
  345. var node = group.item(i);
  346. if (node.childNodes.length === 2) {
  347. var twovars = [];
  348. for (var j = 0, jlen = 2; j < jlen; j += 1) {
  349. var child = node.childNodes.item(j);
  350. if (child.childNodes.length === 0) {
  351. twovars.push(child.getAttribute('variable'));
  352. if (child.getAttribute('suffix')
  353. || child.getAttribute('prefix')) {
  354. twovars = [];
  355. break;
  356. }
  357. }
  358. }
  359. if (twovars.indexOf("publisher") > -1 && twovars.indexOf("publisher-place") > -1) {
  360. node.setAttribute('has-publisher-and-publisher-place', true);
  361. }
  362. }
  363. }
  364. };
  365. CSL_CHROME.prototype.addMissingNameNodes = function(myxml) {
  366. var nameslist = myxml.getElementsByTagName("names");
  367. for (var i = 0, ilen = nameslist.length; i < ilen; i += 1) {
  368. var names = nameslist.item(i);
  369. var namelist = names.getElementsByTagName("name");
  370. if ((!namelist || namelist.length === 0)
  371. || names.parentNode.tagName.toLowerCase() !== "substitute") {
  372. var doc = names.ownerDocument;
  373. var name = doc.createElement("name");
  374. names.appendChild(name);
  375. }
  376. }
  377. };
  378. CSL_CHROME.prototype.addInstitutionNodes = function(myxml) {
  379. var names, thenames, institution, theinstitution, name, thename, xml, pos, len;
  380. names = myxml.getElementsByTagName("names");
  381. for (pos = 0, len = names.length; pos < len; pos += 1) {
  382. thenames = names.item(pos);
  383. name = thenames.getElementsByTagName("name");
  384. if (name.length == 0) {
  385. continue;
  386. }
  387. institution = thenames.getElementsByTagName("institution");
  388. if (institution.length == 0) {
  389. theinstitution = this.importNode(myxml.ownerDocument, this.institution);
  390. theinstitutionpart = theinstitution.getElementsByTagName("institution-part").item(0);
  391. thename = name.item(0);
  392. thenames.insertBefore(theinstitution, thename.nextSibling);
  393. for (var j = 0, jlen = CSL.INSTITUTION_KEYS.length; j < jlen; j += 1) {
  394. var attrname = CSL.INSTITUTION_KEYS[j];
  395. var attrval = thename.getAttribute(attrname);
  396. if (attrval) {
  397. theinstitutionpart.setAttribute(attrname, attrval);
  398. }
  399. }
  400. var nameparts = thename.getElementsByTagName("name-part");
  401. for (var j = 0, jlen = nameparts.length; j < jlen; j += 1) {
  402. if ('family' === nameparts[j].getAttribute('name')) {
  403. for (var k = 0, klen = CSL.INSTITUTION_KEYS.length; k < klen; k += 1) {
  404. var attrname = CSL.INSTITUTION_KEYS[k];
  405. var attrval = nameparts[j].getAttribute(attrname);
  406. if (attrval) {
  407. theinstitutionpart.setAttribute(attrname, attrval);
  408. }
  409. }
  410. }
  411. }
  412. }
  413. }
  414. };