Sample code for 30+ languages & platforms
Xbase++

HTML Table to CSV

See more HTML-to-XML/Text Examples

Demonstrates a method for converting an HTML table to a CSV file.

Note: This example requires Chilkat v9.5.0.77 or greater.

Chilkat Xbase++ Downloads

Xbase++
LOCAL nSuccess
LOCAL oHttp
LOCAL oBdHtml
LOCAL oHtx
LOCAL oSbXml
LOCAL oXml
LOCAL nNumRemoved
LOCAL i
LOCAL nCount_i
LOCAL cTable_role
LOCAL cTable_data_scrollx
LOCAL cTable_data_sortdirection
LOCAL cTable_data_sorton
LOCAL cTable_id
LOCAL j
LOCAL nCount_j
LOCAL cTr_role
LOCAL k
LOCAL nCount_k
LOCAL cTagPath
LOCAL cText
LOCAL oCsv
LOCAL cCsvStr

nSuccess := 0

//  This example requires the Chilkat API to have been previously unlocked.
//  See Global Unlock Sample for sample code.

//  First download the HTML containing the table
oHttp := CreateObject("Chilkat.Http")
oBdHtml := CreateObject("Chilkat.BinData")

nSuccess := oHttp:QuickGetBd("https://example-code.com/data/etf_table.html", oBdHtml)
IF (nSuccess != 1)
    ? oHttp:LastErrorText
    oHttp:destroy()
    oBdHtml:destroy()
    RETURN
ENDIF

//  Convert to XML.
oHtx := CreateObject("Chilkat.HtmlToXml")
oHtx:SetHtmlBd(oBdHtml)

oSbXml := CreateObject("Chilkat.StringBuilder")
oHtx:ToXmlSb(oSbXml)

oXml := CreateObject("Chilkat.Xml")
oXml:LoadSb(oSbXml, 1)

//  Remove attributes and sub-trees we don't need.
//  (In other words, we're getting rid of clutter...)
nNumRemoved := oXml:PruneTag("thead")
nNumRemoved := oXml:PruneAttribute("style")
nNumRemoved := oXml:PruneAttribute("class")

//  Scrub the element and attribute content.
oXml:Scrub("ContentTrimEnds,ContentTrimInside,AttrTrimEnds,AttrTrimInside")

//  Let's see what we have...
? oXml:GetXml()

//  We have the following XML.
//  Copy this XML into the online tool at Generate Parsing Code from XML
//  as a starting point for accessing the data..

//  <?xml version="1.0" encoding="utf-8"?>
//  <root>
//      <html>
//          <head>
//              <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
//          </head>
//          <body text="#000000" bgcolor="#FFFFFF">
//              <div>
//                  <div>
//                      <table role="grid" data-scrollx="true" data-sortdirection="desc" data-sorton="-1"/>
//                  </div>
//              </div>
//              <div>
//                  <table id="topHoldingsTable" role="grid" data-scrollx="true" data-sortdirection="desc" data-sorton="-1">
//                      <tbody>
//                          <tr role="row">
//                              <td>
//                                  <text>ITUB4</text>
//                              </td>
//                              <td>
//                                  <text>ITAU UNIBANCO HOLDING PREF SA</text>
//                              </td>
//                              <td>
//                                  <text>Financials</text>
//                              </td>
//                              <td>
//                                  <text>Brazil</text>
//                              </td>
//                              <td>
//                                  <text>10.94</text>
//                              </td>
//                              <td>
//                                  <text>998,954,813.73</text>
//                              </td>
//                          </tr>
//                          <tr role="row">
//                              <td>
//                                  <text>BBDC4</text>
//                              </td>
//                              <td>
//                                  <text>BANCO BRADESCO PREF SA</text>
//                              </td>
//                              <td>
//                                  <text>Financials</text>
//                              </td>
//                              <td>
//                                  <text>Brazil</text>
//                              </td>
//                              <td>
//                                  <text>9.01</text>
//                              </td>
//                              <td>
//                                  <text>822,164,622.75</text>
//                              </td>
//                          </tr>
//  			...
//  			...
//  			...
//                      </tbody>
//                  </table>
//              </div>
//          </body>
//      </html>
//  </root>

//  This is the code generated by the online tool:
//  

i := 0
nCount_i := oXml:NumChildrenHavingTag("html|body|div")
DO WHILE i < nCount_i
    oXml:I := i
    cTable_role := oXml:ChilkatPath("html|body|div[i]|div|table|(role)")
    cTable_data_scrollx := oXml:ChilkatPath("html|body|div[i]|div|table|(data-scrollx)")
    cTable_data_sortdirection := oXml:ChilkatPath("html|body|div[i]|div|table|(data-sortdirection)")
    cTable_data_sorton := oXml:ChilkatPath("html|body|div[i]|div|table|(data-sorton)")
    cTable_id := oXml:ChilkatPath("html|body|div[i]|table|(id)")
    cTable_role := oXml:ChilkatPath("html|body|div[i]|table|(role)")
    cTable_data_scrollx := oXml:ChilkatPath("html|body|div[i]|table|(data-scrollx)")
    cTable_data_sortdirection := oXml:ChilkatPath("html|body|div[i]|table|(data-sortdirection)")
    cTable_data_sorton := oXml:ChilkatPath("html|body|div[i]|table|(data-sorton)")
    j := 0
    nCount_j := oXml:NumChildrenHavingTag("html|body|div[i]|table|tbody|tr")
    DO WHILE j < nCount_j
        oXml:J := j
        cTr_role := oXml:ChilkatPath("html|body|div[i]|table|tbody|tr[j]|(role)")
        k := 0
        nCount_k := oXml:NumChildrenHavingTag("html|body|div[i]|table|tbody|tr[j]|td")
        DO WHILE k < nCount_k
            oXml:K := k
            cText := oXml:GetChildContent("html|body|div[i]|table|tbody|tr[j]|td[k]|text")
            k := k + 1
        ENDDO
        j := j + 1
    ENDDO
    i := i + 1
ENDDO

//  Let's modify the above code to build the CSV.
oCsv := CreateObject("Chilkat.Csv")
oCsv:SetColumnName(0, "Ticker")
oCsv:SetColumnName(1, "Name")
oCsv:SetColumnName(2, "Sector")
oCsv:SetColumnName(3, "Country")
oCsv:SetColumnName(4, "Weight")
oCsv:SetColumnName(5, "Notional Vaue")

i := 0
nCount_i := oXml:NumChildrenHavingTag("html|body|div")
DO WHILE i < nCount_i
    oXml:I := i
    j := 0
    nCount_j := oXml:NumChildrenHavingTag("html|body|div[i]|table|tbody|tr")
    DO WHILE j < nCount_j
        oXml:J := j
        k := 0
        nCount_k := oXml:NumChildrenHavingTag("html|body|div[i]|table|tbody|tr[j]|td")
        DO WHILE k < nCount_k
            oXml:K := k
            oCsv:SetCell(j, k, oXml:GetChildContent("html|body|div[i]|table|tbody|tr[j]|td[k]|text"))
            k := k + 1
        ENDDO
        j := j + 1
    ENDDO
    i := i + 1
ENDDO

oCsv:SaveFile("qa_output/brasil_etf.csv")
cCsvStr := oCsv:SaveToString()
? cCsvStr

//  Our CSV looks like this:
//  Ticker,Name,Sector,Country,Weight,Notional Vaue
//  ITUB4,ITAU UNIBANCO HOLDING PREF SA,Financials,Brazil,10.94,"998,954,813.73"
//  BBDC4,BANCO BRADESCO PREF SA,Financials,Brazil,9.01,"822,164,622.75"
//  VALE3,CIA VALE DO RIO DOCE SH,Materials,Brazil,8.60,"785,290,260.07"
//  PETR4,PETROLEO BRASILEIRO PREF SA,Energy,Brazil,5.68,"518,124,434.10"
//  PETR3,PETROBRAS,Energy,Brazil,4.86,"443,254,438.53"
//  B3SA3,B3 BRASIL BOLSA BALCAO SA,Financials,Brazil,4.57,"417,636,740.16"
//  ABEV3,AMBEV SA,Consumer Staples,Brazil,4.57,"417,216,913.63"
//  BBAS3,BANCO DO BRASIL SA,Financials,Brazil,3.25,"296,921,232.15"
//  ITSA4,ITAUSA INVESTIMENTOS ITAU PREF SA,Financials,Brazil,2.90,"265,153,684.52"
//  LREN3,LOJAS RENNER SA,Consumer Discretionary,Brazil,2.25,"205,832,175.98"
//

oHttp:destroy()
oBdHtml:destroy()
oHtx:destroy()
oSbXml:destroy()
oXml:destroy()
oCsv:destroy()