skip to Main Content

I have a list from an xml document which contain badges and failedaccesses elements which have attributes. I want to get all the prime numbered badge elements. How can I do this? I have tried using a function to retrieve the prime numbers, but I only get the value. I want to return the badge elements as a whole.

HTML Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mcdonald's Task</title>
    <style>
        table {
          font-family: arial, sans-serif;
          border-collapse: collapse;
          width: 100%;
        }
        
        td, th {
          border: 1px solid #dddddd;
          text-align: left;
          padding: 8px;
        }
        
        tr:nth-child(even) {
          background-color: #dddddd;
        }
        </style>
</head>
<body>

    <h1>Task</h1>
    <button id="action">Download csv</button>


    <table id="html-data-table">
        <tr>
          <th>ID</th>
          <th>Failed Access</th>
        </tr>
      </table>
    
    <script src="app.js"></script>
</body>
</html>

JavaScript Code

// Function to find Prime numbers in badges 
const testPrime = (num) =>  {

    let res = [];

    let isPrime = true;

    if(num <= 1) {
        console.log("1 is neither prime nor composite number")
    } else if(num > 1) {
        for(let i = 2; i < num; i++) {
            if(num % i == 0) {
                isPrime = false;
                break;
            }
        }
    }

    if(isPrime) {
        // console.log(`${num} is a prime number`);
        res.push(num);
        return res
    }
  }



const getData = function() {
    fetch("task.xml").then(response => {
        return response.text()
    }).then(xmlString => {
        const xmlDocument = new DOMParser().parseFromString(xmlString, 'text/xml');

        const accessControl = xmlDocument.querySelectorAll('accessControl');
        let childElements = accessControl[0].children;
        let refinedData = [...childElements];

        // Badges Arrays
        const allBadges = refinedData[0];
        const allBadgesNow = allBadges.querySelectorAll('badge');
        const badgesArr = [...allBadgesNow];

        // Failed Access Array
        const allFailedAccess = refinedData[1];
        const allFailedAccessNow = allFailedAccess.querySelectorAll('accessattempt');
        const failedAccessArr = [...allFailedAccessNow];

        // Loop for badges 

        badgesArr.forEach(item => {
        const  attributes = item.attributes;
        const id = attributes[0].value;
        const primeNum = testPrime(id);
        // Nested forEachLoop
        failedAccessArr.map(itemTwo => {
            const badgeLink = itemTwo.getAttribute('badge');
            const accessedDate = itemTwo.getAttribute('accessedDate');
        })       
        })
    });
}

const btn = document.getElementById('action');
btn.addEventListener('click', getData);

This list is much longer than this (30000 elements), so I just copied some of it here to show the data format.

XML Document

<?xml version="1.0" encoding="utf-8"?>
<accessControl>
    <badges>
        <badge number="1" passcode="535335" issued="02/03/2016 00:00:00"/>
        <badge number="2" passcode="988798" issued="23/02/1997 00:00:00"/>
        <badge number="3" passcode="823603" issued="22/08/2003 00:00:00"/>
        <badge number="4" passcode="767876" issued="12/11/1999 00:00:00"/>
        <badge number="5" passcode="905922" issued="19/11/2009 00:00:00"/>
        <badge number="6" passcode="773912" issued="11/08/2015 00:00:00"/>
        <badge number="7" passcode="689032" issued="24/01/2003 00:00:00"/>
        <badge number="8" passcode="158703" issued="03/01/2010 00:00:00"/>
        <badge number="9" passcode="877498" issued="10/11/2011 00:00:00"/>
        <badge number="10" passcode="960573" issued="19/06/2000 00:00:00"/>
        <badge number="11" passcode="936346" issued="16/10/2018 00:00:00"/>
        <badge number="12" passcode="472985" issued="19/09/2008 00:00:00"/>
        <badge number="13" passcode="113143" issued="28/07/2010 00:00:00"/>
        <badge number="14" passcode="512691" issued="20/11/2012 00:00:00"/>
        <badge number="15" passcode="112630" issued="02/03/2022 00:00:00"/>
        <badge number="16" passcode="656349" issued="19/12/2021 00:00:00"/>
        <badge number="17" passcode="919450" issued="03/11/2002 00:00:00"/>
        <badge number="18" passcode="359069" issued="28/12/2001 00:00:00"/>
        <badge number="19" passcode="493035" issued="12/10/2003 00:00:00"/>
        <badge number="20" passcode="806352" issued="15/06/2004 00:00:00"/>
        <badge number="21" passcode="116876" issued="06/08/2003 00:00:00"/>
        <badge number="22" passcode="670517" issued="03/10/2000 00:00:00"/>
        <badge number="23" passcode="841163" issued="10/10/2014 00:00:00"/>
        <badge number="24" passcode="746314" issued="18/08/2003 00:00:00"/>
        <badge number="25" passcode="805226" issued="02/11/2008 00:00:00"/>
        <badge number="26" passcode="596947" issued="27/04/2007 00:00:00"/>
        <badge number="27" passcode="602959" issued="17/11/2019 00:00:00"/>
        <badge number="28" passcode="887057" issued="17/08/2013 00:00:00"/>
        <badge number="29" passcode="393407" issued="07/07/2009 00:00:00"/>
        <badge number="30" passcode="154477" issued="31/05/2002 00:00:00"/>
        <badge number="31" passcode="859293" issued="30/04/1998 00:00:00"/>
        <badge number="32" passcode="240500" issued="09/01/2022 00:00:00"/>
        <badge number="33" passcode="912206" issued="11/01/2018 00:00:00"/>
        <badge number="34" passcode="829381" issued="14/11/2005 00:00:00"/>
   </badges>

   <failedaccesses>
        <accessattempt badge="2347" accessedDate="08/10/2022 00:00:00">
            <passcodeentered value="560775"/>
        </accessattempt>
        <accessattempt badge="2617" accessedDate="24/05/2023 00:00:00">
            <passcodeentered value="993700"/>
        </accessattempt>
        <accessattempt badge="1111" accessedDate="03/07/2023 00:00:00">
            <passcodeentered value="846599"/>
        </accessattempt>
        <accessattempt badge="300" accessedDate="13/09/2022 00:00:00">
            <passcodeentered value="308523"/>
        </accessattempt>
        <accessattempt badge="1509" accessedDate="09/09/2022 00:00:00">
            <passcodeentered value="149089"/>
        </accessattempt>
        <accessattempt badge="218" accessedDate="05/12/2022 00:00:00">
            <passcodeentered value="140284"/>
        </accessattempt>
        <accessattempt badge="1513" accessedDate="04/10/2022 00:00:00">
            <passcodeentered value="791493"/>
        </accessattempt>
        <accessattempt badge="1718" accessedDate="27/04/2023 00:00:00">
            <passcodeentered value="258773"/>
        </accessattempt>
        <accessattempt badge="2214" accessedDate="16/04/2023 00:00:00">
            <passcodeentered value="845822"/>
        </accessattempt>
        <accessattempt badge="531" accessedDate="03/11/2022 00:00:00">
            <passcodeentered value="680486"/>
        </accessattempt>
        <accessattempt badge="55" accessedDate="11/04/2023 00:00:00">
            <passcodeentered value="751332"/>
        </accessattempt>
        <accessattempt badge="1772" accessedDate="01/10/2022 00:00:00">
            <passcodeentered value="867818"/>
        </accessattempt>
        <accessattempt badge="453" accessedDate="25/08/2022 00:00:00">
            <passcodeentered value="852861"/>
        </accessattempt>
        <accessattempt badge="1709" accessedDate="30/06/2023 00:00:00">
            <passcodeentered value="520909"/>
        </accessattempt>
        <accessattempt badge="1919" accessedDate="20/02/2023 00:00:00">
            <passcodeentered value="308020"/>
        </accessattempt>
        <accessattempt badge="336" accessedDate="19/08/2022 00:00:00">
            <passcodeentered value="338791"/>
        </accessattempt>
        <accessattempt badge="122" accessedDate="03/01/2023 00:00:00">
            <passcodeentered value="972854"/>
        </accessattempt>
   </failedaccesses>
<accessControl>
    

2

Answers


  1. You can get all the attributes from the object using map and then use filter to filter out the elements you don’t want.

    const getPrimeBadges = (myDocument) => {
        const accessControl = myDocument.querySelectorAll('accessControl');
    
        const badges = [...accessControl[0].children[0].querySelectorAll('badge')];
    
        const primeBadges = badges
            .map((item) => {
                return {
                    id: Number(item.attributes[0].value),
                    issued: item.getAttribute('issued'),
                    passcode: item.getAttribute('passcode'),
                };
            })
            .filter((badge) => {
                return testPrime(badge.id);
            });
        return primeBadges;
    };
    

    This will give you a list of objects like this:

    [
      { id: 1, issued: '02/03/2016 00:00:00', passcode: '535335' },
      { id: 2, issued: '23/02/1997 00:00:00', passcode: '988798' },
      { id: 3, issued: '22/08/2003 00:00:00', passcode: '823603' },
      { id: 5, issued: '19/11/2009 00:00:00', passcode: '905922' },
      { id: 7, issued: '24/01/2003 00:00:00', passcode: '689032' },
      { id: 11, issued: '16/10/2018 00:00:00', passcode: '936346' },
      { id: 13, issued: '28/07/2010 00:00:00', passcode: '113143' },
      { id: 17, issued: '03/11/2002 00:00:00', passcode: '919450' },
      { id: 19, issued: '12/10/2003 00:00:00', passcode: '493035' },
      { id: 23, issued: '10/10/2014 00:00:00', passcode: '841163' },
      { id: 29, issued: '07/07/2009 00:00:00', passcode: '393407' },
      { id: 31, issued: '30/04/1998 00:00:00', passcode: '859293' }
    ]
    

    You could also use reduce to do the map + filter in 1 step, but I find that a little harder to read for people just learning about these array functions.

    N.B. I think there are more efficient ways to determine if a number is prime, so you might want to take a look into that as well.

    Login or Signup to reply.
    1. Function for prime number can be improved
    2. Logic for finding prime numbered badges has been fixed
    3. Looping through failed badges to find last failure dates requires more conditions which have been added
    4. Looping through badges array seems redundant – could be achieved by just looping through failed badges array. this has not been implemented in below code, but something to consider
    // Function to find Prime numbers in badges
    const testPrime = (num) => {
      for (let i = 2, s = Math.sqrt(num); i <= s; i++) {
        if (num % i === 0) return false;
      }
      return num > 1;
    };
    
    const getData = function () {
      fetch("task.xml")
        .then((response) => {
          return response.text();
        })
        .then((xmlString) => {
          const xmlDocument = new DOMParser().parseFromString(
            xmlString,
            "text/xml"
          );
    
          const accessControl = xmlDocument.querySelectorAll("accessControl");
          let childElements = accessControl[0].children;
          let refinedData = [...childElements];
    
          // Badges Arrays
          const allBadges = refinedData[1];
          const allBadgesNow = allBadges.querySelectorAll("badge");
          const badgesArr = [...allBadgesNow];
    
          // Failed Access Array
          const allFailedAccess = refinedData[2];
          const allFailedAccessNow =
            allFailedAccess.querySelectorAll("accessattempt");
          const failedAccessArr = [...allFailedAccessNow];
    
          // Loop for badges
    
          const finalFailedDates = [];
    
          badgesArr.forEach((item) => {
            const attributes = item.attributes;
            const id = attributes[0].value;
            const primeNum = testPrime(id);
            console.log({ primeNum });
            let failedAccessDate = null;
            if (primeNum) {
              // Nested forEachLoop
              failedAccessArr.map((itemTwo) => {
                const badgeLink = itemTwo.getAttribute("badge");
                const accessedDate = itemTwo.getAttribute("accessedDate");
                if (badgeLink === id) {
                  console.log({ badgeLink, accessedDate });
                  if (failedAccessDate) {
                    const newAccessDate = new Date(accessedDate).getTime();
                    if (newAccessDate > new Date(failedAccessDate).getTime()) {
                      failedAccessDate = accessedDate;
                    }
                  } else failedAccessDate = accessedDate;
                }
              });
              if (failedAccessDate) finalFailedDates.push({ id, failedAccessDate });
            }
          });
          console.log({ finalFailedDates });
          //Additionally do not see a need to loop through badgesArr at all, can just loop through failedDates and find primen umber + recent failure
        });
    };
    
    const btn = document.getElementById("action");
    btn.addEventListener("click", getData);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search