skip to Main Content

I’m reading an XML file and displaying it on a webpage.
I’m using a JS script which reads the XML file and displays the information in a table.
However, when the page loads the information inside the cells shows "UNDEFINED".
The table should display the person’s name and hearing room information.

I have tried the top solution from this stack overflow article: How to make JavaScript execute after page load?

I have checked for spelling mistakes and the structure of my XML file and read several other articles on stack overflow but with no success.

My JS script:

<!DOCTYPE html>
<html lang="en">
    
<head>
    <meta charset="utf-8"/>
    <title></title>
    <script>
        var client;
        if (window.XMLHttpRequest)
        {
            client = new XMLHttpRequest();
        }
        else 
        {
            client = new ActiveXObject("Microsoft.XMLHTTP");
        }
        client.open('GET', 'TestData.xml', true);

        
        
        client.onload = function()  // Function to run when the file loads
        {
            // get the response XML
            var xmlDoc = client.responseXML;

            // get the list
            var hearings = xmlDoc.getElementsByTagName("hr");

            
            // get the container where you want to embed the table
            var container = document.getElementById("container");

            // Create a table and put the data inside it
            var tableString = "<table border = '1'>";
                for (i = 0; i < hearings.length; i++)
                {
                    tableString += "<tr><td>";
                    tableString += hearings[i].getElementsByTagName("name")[0].childNodes[0].nodValue;
                    tableString += "<tr><td>";
                    tableString += hearings[i].getElementsByTagName("hearing_room")[0].childNodes[0].nodValue;
                    tableString += "<tr><td>";
                    
                }
                tableString +="</table>";

                // append the table to the container
                container.innerHTML = tableString;
        }

        client.send();
    

    </script>   

    
</head>

<body>
    
    <h1></h1>
    
    <div id="container"></div>
    
</body>

</html>

My XML document:

<?xml version="1.0" ?>
<hearing name="hearing_schedule">
    <hr>
        <name>Michelle</name>
        <hearing_room>M028</hearing_room>
    </hr>
    <hr>
        <name>Matthews</name>
        <hearing_room>M028</hearing_room>
    </hr>
   <hr>
        <name>Anita</name>
        <hearing_room>M028</hearing_room>
    </hr>
</hearing>

2

Answers


  1. Try a different selector, since you only expect one of each element per


    , you should use a single selector, rather than a list selector.

    so, you should be able to use querySelector( )

    var tableString = "<table border = '1'>";
    for (i = 0; i < hearings.length; i++) {
      tableString += "<tr><td>";
      tableString += hearings[i].querySelector("#name").innerText;
      tableString += "<tr><td>";
      tableString += hearings[i].querySelector("hearing_room").innerText;
      tableString += "<tr><td>";
    
    }
    Login or Signup to reply.
  2. You need to avoid accessing the property on the undefined object and define a fallback.

    const foo = undefined;
    
    // operator "?." avoids accessing undefined properties
    console.log(foo?.bar);
    // use the "||" operator
    console.log(foo?.bar || 'fallback');

    Browsers now support the fetch() API. This reduces the needed source and it can be used with async/await.

    Query selector allows to use CSS selectors to fetch nodes. Additionally you can use them on element nodes (make the element node the scope of the selector) – avoiding using an counter/index.

    Last you should create the DOM elements directly, not as an HTML string.

    fetchAndDisplay(
      document.querySelector("#container tbody")
    );
    
    // define the function as async - so it can await results of 
    // other async calls
    async function fetchAndDisplay(container) {
       // wait for the fetched data
       const xml = await fetchXML();
       // clear all nodes inside the target container
       container.textContent = '';
       // fetch all hr elements as an array 
       const hearings = [...xml.querySelectorAll('hr')];
       // append mapped hearings
       container.append(
         ...hearings.map(
         // map hearing into table row
         function (hr) {
           // create row
           const row = document.createElement('tr');
           // create + append cells, use querySelector to fetch content
           row.append(
             createTableCell(hr.querySelector('name')?.textContent || ''),
             createTableCell(hr.querySelector('hearing_room')?.textContent || ''),
           );
           return row;
         }
       ));
    }
    
    function createTableCell(textContent) {
       const cell = document.createElement('td');
       cell.textContent = textContent;
       return cell;
    }
    
    async function fetchXML() {
      // fetch + parse XML, use string for example
      return (new DOMParser).parseFromString(
        // await fetch('http://...')
        `<?xml version="1.0" ?>
    <hearing name="hearing_schedule">
        <hr>
            <name>Michelle</name>
            <hearing_room>M028</hearing_room>
        </hr>
        <hr>
            <name>Matthews</name>
            <hearing_room>M028</hearing_room>
        </hr>
       <hr>
            <name>Anita</name>
            <hearing_room>M028</hearing_room>
        </hr>
    </hearing>`,
        'application/xml'
      );
    }
    <table id="container">
      <tr>
        <th>Name</th>
        <th>Room</th>
      <tr>
      <tbody>
      
      </tbody>
    </table>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search