4
\$\begingroup\$

I need to concatenate the LastName and Initials and all of that authors affiliations. Is there a better way or faster way to do this? I'm very new to working XML in JavaScript.

This is a portion of an XML string that I get back from an API that I parse in JavaScript:

 <AuthorList CompleteYN="Y">
 <Author ValidYN="Y">
 <LastName>Basree</LastName>
 <ForeName>Mustafa M</ForeName>
 <Initials>MM</Initials>
 <AffiliationInfo>
 <Affiliation>The Cancer Center...</Affiliation>
 </AffiliationInfo>
 </Author>
 <Author ValidYN="Y">
 <LastName>Shinde</LastName>
 <ForeName>Neelam</ForeName>
 <Initials>N</Initials>
 <AffiliationInfo>
 <Affiliation>The Comprehensive..</Affiliation>
 </AffiliationInfo>
 </Author>
 <Author ValidYN="Y">
 <LastName>Koivisto</LastName>
 <ForeName>Christopher</ForeName>
 <Initials>C</Initials>
 <AffiliationInfo>
 <Affiliation>Hollings ...</Affiliation>
 </AffiliationInfo>
 <AffiliationInfo>
 <Affiliation>Department ...</Affiliation>
 </AffiliationInfo>
 </Author>
 <Author ValidYN="Y">
 <LastName>Cuitino</LastName>
 <ForeName>Maria</ForeName>
 <Initials>M</Initials>
 <AffiliationInfo>
 <Affiliation>Hollings...</Affiliation>
 </AffiliationInfo>
 <AffiliationInfo>
 <Affiliation>Department ..</Affiliation>
 </AffiliationInfo>
 </Author>
</AuthorList>

my Code:

 let HTMLContent = ""
 parser = new DOMParser();
 xmlDoc = parser.parseFromString(response.data, "text/xml");
 const AuthorsInfo = xmlDoc.querySelectorAll("Author");
 AuthorsInfo.forEach(a => {
 let affiliations = "";
 let AuthorName = "";
 for (var i = 0; i < a.children.length; i++) {
 let tt = a.children[i].nodeName;
 let t = a.children[i].textContent;
 if (tt === "AffiliationInfo") {
 affiliations += a.children[i].textContent;
 affiliations += "<br /><br />";
 } else if (tt === "LastName") {
 AuthorName = a.children[i].textContent;
 } else if (tt === "Initials") {
 AuthorName += " " + a.children[i].textContent;
 AuthorName += "<br /><br />";
 }
 }
 HTMLContent += AuthorName + " " + affiliations;
 });
asked Oct 8, 2019 at 12:36
\$\endgroup\$
1
  • \$\begingroup\$ Can the node loop be improved \$\endgroup\$ Commented Oct 8, 2019 at 13:16

1 Answer 1

4
\$\begingroup\$

Style

  • Inconsistent use of line ending semi colon

  • Undeclared variables parser and xmlDoc

  • Unused code. let t = a.children[i].textContent; t is never used the line should not be there

  • Poor naming

    • Capitalisation of variable names. Only if objects to be instanciated via new token, if accronim (eg HTML, XML) or if a constant (optional). Examples; AuthorsInfo should be authorsInfo, AuthorName as authorName, xmlDoc as XMLDoc.
    • Non descripttive names, a, tt, t
    • Semanticly inacurate names, AuthorsInfo either authorNodes or just authors
  • Use for of loops rather than for if loops if you do not need the index counter

  • Use for of loops rather than Array iterators

  • Function scoped variables should be declared as var and hoisted to the top of the function

Code design

As you have several potential errors in the code (undeclared variables) you should ALWAYS use the directive "use strict" in your code to ensure these types of syntax problems are caught early in the development process.

Always present your code as a function/s. Presenting code as flat global scoped source string is very poor design practice.

Flat code often ends up performing many tasks that should be separated. Writing functions helps you define task roles under clearly named functions.

The parsing of the XML to HTML is more than one task. I suggest you have two functions parseAuthors to extract the author details, and authorsToHTML to create the markup.

Example rewrite

From your code it is unclear as to the nature of the XML. Can authors have no last name, initials, or affiliations. Do authors always have one last name, does the last name always come before the initials. And many more unanswered questions regarding the XML.

The example assumes that the XML given defines the XML.

The example breaks the code into many smaller functions and puts them all together inside a IIF (immediately invoked function). In the real world you would put all the code inside a module.

"use strict";
// As IFF or better as module (No need for use strict if module)
const authors = (() => {
 const AUTHORS = "Author"; 
 const AFFILIATION = "AffiliationInfo";
 const LAST_NAME = "LastName";
 const INITIALS = "Initials";
 const SEP = "<br/><br/>";
 const nodeTxt = (node, name) => (name ? node.querySelector(name) : node).textContent;
 
 function Author(authorNode) {
 const author = {
 lastName: nodeTxt(authorNode, LAST_NAME),
 initials: nodeTxt(authorNode, INITIALS),
 affiliations: []
 }
 for (const affNode of authorNode.querySelectorAll(AFFILIATION)) {
 author.affiliations.push(nodeTxt(affNode));
 }
 return author;
 }
 return {
 parse(XMLString) {
 const authors = [];
 const authorNodes = new DOMParser()
 .parseFromString(XMLString, "text/xml")
 .querySelectorAll("Author");
 for (const authorNode of authorNodes) { authors.push(Author(authorNode)) }
 return authors;
 },
 toHTML(authors) {
 var markup = "";
 for (const author of authors) {
 markup += author.lastName + " " + author.initials + SEP;
 markup += " " + author.affiliations.join(SEP) + SEP;
 }
 return markup;
 },
 };
})();
document.body.innerHTML = authors.toHTML(authors.parse(getXML()));
function getXML() { return `<AuthorList CompleteYN="Y">
<Author ValidYN="Y">
 <LastName>Basree</LastName>
 <ForeName>Mustafa M</ForeName>
 <Initials>MM</Initials>
 <AffiliationInfo>
 <Affiliation>The Cancer Center...</Affiliation>
 </AffiliationInfo>
</Author>
<Author ValidYN="Y">
 <LastName>Shinde</LastName>
 <ForeName>Neelam</ForeName>
 <Initials>N</Initials>
 <AffiliationInfo>
 <Affiliation>The Comprehensive..</Affiliation>
 </AffiliationInfo>
</Author>
<Author ValidYN="Y">
 <LastName>Koivisto</LastName>
 <ForeName>Christopher</ForeName>
 <Initials>C</Initials>
 <AffiliationInfo>
 <Affiliation>Hollings ...</Affiliation>
 </AffiliationInfo>
 <AffiliationInfo>
 <Affiliation>Department ...</Affiliation>
 </AffiliationInfo>
</Author>
<Author ValidYN="Y">
 <LastName>Cuitino</LastName>
 <ForeName>Maria</ForeName>
 <Initials>M</Initials>
 <AffiliationInfo>
 <Affiliation>Hollings...</Affiliation>
 </AffiliationInfo>
 <AffiliationInfo>
 <Affiliation>Department ..</Affiliation>
 </AffiliationInfo>
</Author>
</AuthorList>`
};

answered Oct 9, 2019 at 13:07
\$\endgroup\$
3
  • \$\begingroup\$ Hello, I am a javascript beginner and probably mine is an obvious question: why there is no need to use strict in a module and if there are other cases when not to use strict in javascript code. Thanks in advance. \$\endgroup\$ Commented Oct 10, 2019 at 13:00
  • \$\begingroup\$ @dariosicily Modules are automatically strict mode and it can not be turned off. There are no good reasons not to use strict mode. For more information developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… \$\endgroup\$ Commented Oct 10, 2019 at 16:33
  • \$\begingroup\$ Fantastic- Thank you. I will include much of your rewrite \$\endgroup\$ Commented Oct 10, 2019 at 18:52

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.