Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 14 of 14

Thread: Read table data

  1. #1
    BoB
    BoB is offline
    New to the CF scene
    Join Date
    Jan 2004
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Read table data

    The client browser is IE6.

    How do you read table data posted on a web page into a new frame? Specifically the table data must be seperated from the page coding leaving the raw data.

    The originating url "Property_info" is a frameset.

    <FRAMESET
    frameBorder=NO rows="0.01%, *"><FRAME name=TOP noResize scrolling=no
    src="Real_Property/top.htm"><FRAME name=MAIN
    src="Real_Property/structure.htm"></FRAMESET>

    The data is within the structure.htm file, table id "homedata".

    Objective: Read table data from frame and write into new window seperating field data with commas and rows with semicolan.
    Last edited by BoB; 01-04-2004 at 06:14 AM.

  • #2
    Senior Coder
    Join Date
    Jun 2002
    Location
    Nashua, NH
    Posts
    1,724
    Thanks
    0
    Thanked 0 Times in 0 Posts
    window.getElementById('frameId').getElementById('tableId')

    should get you the table

    However, if you are doing it within your domain, why don't you format the data the way you need on the server
    Last edited by Vladdy; 01-04-2004 at 01:35 PM.
    Vladdy | KL
    "Working web site is not the one that looks the same on common graphical browsers running on desktop computers, but the one that adequately delivers information regardless of device accessing it"

  • #3
    BoB
    BoB is offline
    New to the CF scene
    Join Date
    Jan 2004
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Read table

    Thank you for the suggestion. The result was an error message claiming Object does not support this method.

    I do not have access to the server side. Internal politics.

    We are attempting to extend the capability of the client side without database ( oracle ) and web groups involvement. They have scheduled the changes to occur within a few years.

    The code to access the table must reside in a seperate window. I have attempted to nest the frameset within another frameset to permit access to the table data. Nothing seems to work. Although I have read considerable material my ignorance/inexperience of javascript and the Dom do not help.

    Currently we copy and paste the table data into a spreadsheet. This method is inefficient as we have considerable data to analyse and calculate results within specific periods of time.

    I'll try placing Vladdy's Dom viewer within the frameset to see if all nodes are accessible.
    Last edited by BoB; 01-06-2004 at 03:47 AM.

  • #4
    New to the CF scene
    Join Date
    Jan 2004
    Location
    San Jose, CA
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Here's some sample from the MS site:
    http://msdn.microsoft.com/library/de...tions/rows.asp

    I haven't tried this myself but will need to do something similar quite soon. This task is quite easy if you can do Perl but you said you can't get to the server so have to do it all from the client side.

    Deb

  • #5
    Regular Coder
    Join Date
    Jun 2002
    Location
    Round Rock, Texas
    Posts
    443
    Thanks
    0
    Thanked 0 Times in 0 Posts
    OK, so what you want to do is capture data residing in HTML tables on the client side, yes? Then what? JavaScript cannot save/write data to your hard drive, it was designed that way. OK cookies are a special case; but wholely inadequate for your needs.

    A couple of suggestions:

    XML
    eXtended Markup Language is the "wave of the future" for passing around data in a generic way. But again, this will have to be done server-side. XML involves creating custom-made html tags and surrounding your data w/ them in such a way that the data structure and other relevant info (like field names) is captured as part of the XML. Then the receiver doesn't need to know anything, theoretically about the data he/she/it received before hand.

    But there is a learning curve here that may not be be necessary if:
    • Your data tables / structure won't be changing.
    • This really is a temporary solution

    JavaScript Data Structure
    That's what I did. I had some HTML table data and I read it into an array-of-arrays structure. Now I can manipulate the data any way I want, including building comma delimited strings in your case.

    But, again, can't save it to disk. I built these structures for field validation and cross-fields and cross-record validation.

    I did it with "dynamic" HTML, not the DOM. There are a couple of things I did that allowed me to grab the data on the client side w/out traversing a table structure using the DOM.

    Name each field, i.e. <input> tag
    When the table is build on the server, each <input> tag (think field) is given a name. So it might look like this on the client:
    Code:
    <form name="myDatabase">
    <table>
       . . .
       <tr>
          <td>
             <input name="first_name" value = "Joe Swartz">Joe Swartz
          </td>
           . . .
       </tr>
    The key is that each first_name field, in this case, has the same name. That way we can reference ALL first_name fields, automatically, all at once, as an array. In other words the following gives me a javascript array of all first_name fields:

    build an array of each data structure part (field, record, table)
    Code:
    var firstNames = document.myDatabase.first_name;
    Now to iterate through the array:
    Code:
    for (var i = 0; i < firstNames.length; i++) {
       this_name = firstNames[i].value;
    }
    Thats the core. Now create arrays like this for every field.

    Now you create an object who's properties (variables) match your field names.
    Code:
    function aRecord(fName, lName, howOld) {
       this.first_name = fName;
       this.last_name = lName;
       this.age = howOld;
    }
    Don't be intimidated by the word "object". Note that it looks *exactly* like a function, but instead of "var variableName" we say "this.variableName" to create variables

    Now create an array of records:
    Code:
    var myRecords = new Array();
    
    for (var i=0, i<firstNames.length; i++) {
       myRecords[i] = new aRecord (firstNames[i], lNames[i], ages[i]);
    }
    Now you have the entire HTML table in a single JavaScript structure/object, "myRecords" in this example.

    Now you can build your "string of records":
    Code:
    var recordsString = new String();
    
    for (var i=0; i<myRecords.length; i++) {
       recordsString += myRecords[i].fName + "," +
          myRecords[i].lName + "," +
          myRecords[i].age + 
          "\n";   // end of record
    }
    But what can you do with it outside the immediate client code? You can't save it to disk. But you can custom-build other HTML tables from it to display on this same client. As Vladdy said, you really need to work with it server-side if you're trying to export the data.
    Last edited by RadarBob; 01-12-2004 at 04:57 PM.

  • #6
    Regular Coder
    Join Date
    Jun 2002
    Location
    Round Rock, Texas
    Posts
    443
    Thanks
    0
    Thanked 0 Times in 0 Posts
    OK, this should answer your question

    Warning
    I pulled the getTextValue() & normalizeString() functions from another working program. The rest I made up on the fly and I have not tested the whole package.

    Table structure
    Your table should be structured so as to separate the column headings from the data itself. Ideally you use <thead>, <tbody>, <tfoot> tags to differentiate headings, data, and table footers. But at the very least you need a <tbody> tag. This will make grabbing only the data portion of the table very easy.
    Code:
    <table>
       <tr> <th>...</th></tr>  <!-- rows of table headings -->
    
       <tbody id="tableData">
          <tr>
             <td>
          </tr>        <!-- rows of table data -->
       </tbody>
    </table>
    Now here is code to handle grabbing the "innerText" of table data. We pass in the tbody element then recursively go through the child nodes till we "strike oil." Note that the code is written so that any potential intervening tags like <b>, <i> etc. do not trip it up.

    Code:
    // This code is necessary for browsers that don't reflect the DOM constants
    // (like IE).
       if (document.ELEMENT_NODE == null) {
          document.ELEMENT_NODE = 1;
          document.TEXT_NODE = 3;
    
    tblEl = document.getElementById(id)  //id is "tableData" in this example
    
    var tableRows = tblEle.rows;  
    var rawDataRows = new Array();   //somewhere to put the actual data
    
    for (var i = 0; i <tableRows.length; i++) {
       rawDataRows[i] = new Array();
       var thisRow = tableRows[i];
    
       for (var j=0; j<thisRow.cells.length; j++)
           rawDataRows[i,j] = getTextValue(thisRow.cells[j]);
    }
    
    //=========================================
    
    function getTextValue(el) {
      var i;
      var s;
    
      // Find and concatenate the values of all text nodes contained within the
      // element.
      s = "";
      for (i = 0; i < el.childNodes.length; i++)
        if (el.childNodes[i].nodeType == document.TEXT_NODE)
          s += el.childNodes[i].nodeValue;
        else if (el.childNodes[i].nodeType == document.ELEMENT_NODE &&
                 el.childNodes[i].tagName == "BR")
          s += " ";
        else
          // Use recursion to get text within sub-elements.
          s += getTextValue(el.childNodes[i]);
    
      return normalizeString(s);
    }
    
    // Regular expressions for normalizing white space.
      this.whtSpEnds = new RegExp("^\\s*|\\s*$", "g");
      this.whtSpMult = new RegExp("\\s\\s+", "g");
    
    function normalizeString(s) {
      s = s.replace(whtSpMult, " ");  // Collapse any multiple whites space.
      s = s.replace(whtSpEnds, "");   // Remove leading or trailing white space.
    
      return s;
    }
    Errata
    the HTMLTableRow object property "sectionRowIndex" gives you the "index of this row relative to the entire section" - in our case the <tbody> section.

    You can grag the <tbody> section directly, thus:
    Code:
    var tableBody = getElementById('theTableID').tbodies; //collection of all tbodies in the table

  • #7
    BoB
    BoB is offline
    New to the CF scene
    Join Date
    Jan 2004
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    table extraction

    Thank You RadarBoB for your idea.

    I will give it a try and see if it will work.

    In response to the comment javascript and writing to the harddrive, the following works: Note. It's not my code, pieced together info referenced from internet.

    <HTML>
    <HEAD>
    <HTA:APPLICATION ID = "Alternate"
    APPLICATOINNAME = "homepg"
    BORDER = "thin"
    CAPTION = "yes"
    SHOWINTASKBAR = "yes"
    SINGLEINSTANCE = "yes"
    SYSMENU = "yes"
    WINDOWSTATE = "normal" >
    <SCRIPT LANGUAGE="JavaScript">
    var ForWriting = 2;
    var TriStateFalse = 0;
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var newFile = fso.OpenTextFile("d:\\newfile.xml", ForWriting, true, TriStateFalse);
    newFile.WriteLine ("<?xml version=1.0?>");
    // Write a newline character to the file.
    newFile.WriteBlankLines(1) ;
    // Write a line.
    newFile.Write ("<rs:dbtype=str>");
    newFile.WriteBlankLines(1) ;
    newFile.Write ("</rs:data>");
    newFile.Close();
    </SCRIPT>
    </HEAD>
    <TITLE>XML APPLICATION</TITLE>
    <BODY>
    </BODY>
    </HTML>

  • #8
    Smokes a Lot
    Join Date
    Jul 2003
    Location
    CA, USA
    Posts
    1,594
    Thanks
    5
    Thanked 20 Times in 20 Posts
    BoB.

    That is actually a mix of Javascript and ActiveX - Javascript alone really can't access the file system. Once you get the table data that will be an efficient way of transposing it to your HD. I have the same "Internal Political" problems that prevent me from using server side scripting and have found that Active X is a viable alternative when mixed with a network drive. So long as your data is not sensitive as it is extremly less secure.

    Basscyst
    Helping to build a bigger box. - Adam Matthews

  • #9
    BoB
    BoB is offline
    New to the CF scene
    Join Date
    Jan 2004
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Read out table data

    So far no success!

    The following site contains a table with element ID's.

    http://cita.rehab.uiuc.edu/courses/2...e-complex.html

    Who know's how to read out the Hotel cost for say, Seattle?

    If you can script a page to read the above described data into a page of your design, my problem is solved.

    From my local page, I cannot seem to get a reference to an external table? It shouldn't be a problem for browser security. The data will simply be manipulated and stored on the client HD.

  • #10
    Senior Coder
    Join Date
    Jun 2002
    Location
    Nashua, NH
    Posts
    1,724
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Here is the table (better markup with removed accessibility attributes)
    Code:
    <table id="mytable">
    <caption>Travel Expense Report</caption>
    <thead>
    <tr><th></th><th>Meals</th><th>Hotels</th><th>Transport</th><th>Subtotals</th></tr>
    </thead>
    <tbody>
    <tr><th colspan="5">San Jose</th></tr>
    <tr><td>25-Aug-97</td><td>37.74</TD><td>112.00</TD><td>45.00</TD><td></td></tr>
    <tr><td>26-Aug-97</td><td>27.28</td><td>112.00</td><td>45.00</td><td></td></tr>
    <tr><td>subtotals</td><td>65.02</td><td>224.00</td><td>90.00</td><td>379.02</td></tr>
    <tr><th colspan="5">Seattle</th></tr>
    <tr><td>27-Aug-97</td><td>96.25</td><td>109.00</td><td>36.00</td><td></td></tr>
    <tr><td>28-Aug-97</td><td>35.00</td><td>109.00</td><td>36.00</td><td></td></tr>
    <tr><td>subtotals</TD><td>131.25</td><td>218.00</td><td>72.00</td><td>421.25</td></tr>
    <tr><th>Totals</th><td>196.27</td><td>442.00</td><td>162.00</td><td>800.27</td></tr>
    </tbody>
    </table>
    Then a function to read all your table data in to an array will look like this:
    Code:
    
    function readTableData(tbl)
      { tbl.tabledata = new Array(); // initialize array  
        bodyrows = tbl.getElementsByTagName('tbody')[0].getElementsByTagName('tr'); // get collection of table body rows.
        for(var i=0; i<bodyrows.length; i++)   // iterate through table rows
          { tbl.tabledata.push(new Array()); //create new array for row elements and push it in tabledata array
            for(var j=0; j<bodyrows[i].childNodes.length; j++) // iterate through table row child nodes
              { var childNode = bodyrows[i].childNodes[j]; // child node to a local variable
                if(/th/i.test(childNode.nodeName) || /td/i.test(childNode.nodeName)) // if the child node is "th" or "td" (gecko throws empty text nodes in)
                  { if(childNode.firstChild) // make sure it is not an empty node
                     tbl.tabledata[i].push(childNode.firstChild.nodeValue) // assume that <td> or <th> element has no other children but the text node containing the data
                  } 
              }
          }
        return tbl.tabledata;
      }
    
    Call the function readTableData(document.getElementById('mytable'));


    Then just manipulate the array to get the info
    Last edited by Vladdy; 01-26-2004 at 09:54 PM.
    Vladdy | KL
    "Working web site is not the one that looks the same on common graphical browsers running on desktop computers, but the one that adequately delivers information regardless of device accessing it"

  • #11
    Regular Coder
    Join Date
    Jun 2002
    Location
    Round Rock, Texas
    Posts
    443
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Vladdy's code is very concise. But I wonder if it doesn't cause you to lose the context of the data. Sure it grabs the raw data but then how do you tell you've grabbed a location or a "travel record" for that specific location?

    I was thinking that you take advantage of the "axis" and "headers" attributes.

    Then, in code, "peel away" the "layers" of the table, building javascript objects as you go. For example. Scan the table for axis = 'location'. Build an array of those.

    Then using this JS array of locations scan the table (once per location) for data matching that location (you'd have to parse the 'headers' attribute) and build and array of data records as you find them.

    This may seem like unnecessary work - lots of table scans. But this is a "divide and conquer" method rather than an "all at once" method.

    My spidey sense says this is a better modular / step-wise way to tackle the problem. Easier to test in stages.

    Whatever you do definitely write some pseudo-code first!

  • #12
    Senior Coder
    Join Date
    Jun 2002
    Location
    Nashua, NH
    Posts
    1,724
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I do not see how it impaires data access given the particular data structure:
    If you want to "scroll" to the particular city data:

    var i=0;
    for(i; i<tabledata.length; i++)
    { if(tabledata[i][0] == "Seattle") break;
    }
    i++; // gets you to the first dates row;
    //enumerate through dates:
    for(i; i<tabledata.length; i++)
    { if(tabledata[i][0] == "subtotal") break;
    // do what you need with data, for example: get Hotels cost for the date:
    alert('Date: ' + tabledata[i][0] + ' Hotels Cost: ' + tabledata[i][2]);
    }
    //Now i is at the subtotals row - again do what you need:
    alert('Overall hotels for Seattle: ' + tabledata[i][2]);

    turn it into a function that takes city name as an arguement and returns the data you are looking for and you are all set. You can even define your second indexes to make life easier:

    var _MEALS = 1;
    var _HOTELS = 2;
    ....
    Last edited by Vladdy; 01-26-2004 at 11:20 PM.
    Vladdy | KL
    "Working web site is not the one that looks the same on common graphical browsers running on desktop computers, but the one that adequately delivers information regardless of device accessing it"

  • #13
    BoB
    BoB is offline
    New to the CF scene
    Join Date
    Jan 2004
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    reference external URL table

    I appreciate the code for reading in the table data. The underlying problem is unresolved.

    http://cookiecrook.com/AIR/2003/trai...le_headers.htm

    Vladdy's code does not show how to pass a reference from the website mentioned to the readTableData function. How do you pass the URL containing the table ID to the tbl variable ?

    Maybe it is best not to use the DOM. Perhaps it is best to parse URL as given in posting: Reading file content
    Last edited by BoB; 01-27-2004 at 05:49 PM.

  • #14
    Regular Coder
    Join Date
    Jun 2002
    Location
    Round Rock, Texas
    Posts
    443
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Will this work?
    Create an anchor tag and using DOMage grab the table's ID. Must make one of two assumptions. (1) you know the table ID or (2) there is only one table on the page.

    The table id is passed in the URL, and the receiving page needs to know that variable's name to grab it from the URL.

    Code:
    <html>
     <head>
    function grabTableID () {
       var theTable = getElementsByName('table');
       var tableid    = theTable[0].id;
    
       // or, var tableid = getElementById('myTable').id;
    
       getElementById('engage').href = "http://whateverpage.htm?tableID=" + tableid;
    }
     </head>
    
     <body onload='grabTableID();'>
       <table id='myTable'>
          . . .
       </table>
    
       <a id='engage'  href=''>send table ID to another web page</a> 
    
    </body>
    
    
    
    </html>


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •