Cristobal,
No me habia dado cuenta de que los TR no estaban, me guiaba por la imagen que puso Jose Luis. Te comento lo que había estado pensando, es bastante parecido a lo tuyo, con algunos detalles
1) Una tabla HTML está siempre encerrada entre '<table' y '</table>', por lo que con eso sacamos el sobrante de los datos. Nótese que digo '<table' y no '<table>', como el tag puede tener atributos es genérico.
2) dentro de ese código, cada fila está separada con '<tr'. No digo que termine con '</tr> porque el tag de cierre es opcional y, aunque generalmente está, no podemos confiarnos. Con esto separamos cada línea de datos
3) en cada línea, cada celda está separada por '<td', el cierre es opcional por lo que no se considera. Con esto separamos cada elemento en una linea.
4) cada elemento tendrá cosas irrelevantes que podemos quitar porque están encerradas entre '<>' porque son tags de html. Con eso deberíamos tener todo limpio. Entonces:
- Code: Select all Expand view
#include 'Fivewin.ch'
#include 'debug.ch'
#xcommand TEXT INTO <v> => #pragma __cstream|<v>:=%s
#xcommand TEXT INTO <v> ADDITIVE => #pragma __cstream|<v>+=%s
REQUEST HB_CODEPAGE_LTWIN
REQUEST HB_LANG_LT
REQUEST HB_GT_GUI
//------------------------------------------------------------------------------
FUNCTION Main()
//------------------------------------------------------------------------------
LOCAL cCode
TEXT INTO cCode
<table cellspacing="0" cellpadding="3" rules="all" bordercolor="Black" border="1" id="dgModelUser" bgcolor="#CCCCFF" width="400">
<tr bgcolor="#AAAADD">
<td><font face="Verdana" size="1">Model</font></td><td><font face="Verdana" size="1">Type</font></td><td><font face="Verdana" size="1">Sub Type</font></td><td><font face="Verdana" size="1">Serial Nbr</font></td><td><font face="Verdana" size="1">Source</font></td>
</tr><tr>
<td><font face="Verdana" size="1">330M</font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1">ALL</font></td><td><font face="Verdana" size="1">CSS </font></td>
</tr><tr>
<td><font face="Verdana" size="1">330M</font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1">A10196-A10211</font></td><td><font face="Verdana" size="1">OTHER </font></td>
</tr><tr>
<td><font face="Verdana" size="1">3D94</font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1">PIPS </font></td>
</tr><tr>
<td><font face="Verdana" size="1">4D105</font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1">PIPS </font></td>
</tr><tr>
<td><font face="Verdana" size="1">4D94</font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1"> </font></td><td><font face="Verdana" size="1">PIPS </font></td>
</tr>
ENDTEXT
XBrowser( TableToArray( cCode ) )
//------------------------------------------------------------------------------
FUNCTION TableToArray( cText )
//------------------------------------------------------------------------------
LOCAL aTRs := {}
LOCAL aTDs
LOCAL nAt, nFrom, cTR, cTD
// tags a remover de forma rápida para reducir el volumen de datos a procesar.
aEval( {'</font>', '</span>', '<strong>', '</strong>', '<b>', '</b>', '<p>', '</p>', '<li>', '</li>', '<ol>', '</ol>'}, ;
{|x| cText:= StrTran( cText, x ) } )
// Para cada TR, que identificamos por los tags '<tr'
DO WHILE ( nFrom:= At( '<tr', cText ) ) > 0
IF ( nAt:= At('<tr', SubStr( cText, nFrom+3 ) ) ) == 0 // es la ultima fila
nAt:= Len( cText )
ENDIF
cTR:= SubStr( cText, nFrom, nAt+2 ) // cTR es la linea
cText:= SubStr(cText, nFrom+nAt+2) // Eliminamos la linea del texto a procesar
// Lo extraemos del texto remanente y creamos un array con cada td de información
aTDs:= {}
// Para cada TD, que identificamos por los tags '<td' ...
DO WHILE ( nFrom:= At( '<td', cTR ) ) > 0
IF ( nAt:= At('<td', SubStr( cTR, nFrom+3 ) ) ) == 0 // es la ultima celda
nAt:= Len( cTR )
ENDIF
cTD:= SubStr( cTR, nFrom, nAt+2 )
cTR:= SubStr(cTR, nFrom+nAt+2)
// Remover los todos los tags (entre '<' y '>') para dejar el text en limpio
DO WHILE ( nAt:= At('>', cTD) ) > 0
nFrom:= At( '<', cTD )
cTD:= Left( cTD, nFrom - 1) + SubStr( cTD, nAt+1 )
ENDDO
// sacar espacios que están como html-entities,
cTD:= StrTran( cTD, ' ', ' ' )
// IF !Empty( cTD )
// MsgInfo( cTD )
// ENDIF
aAdd( aTDs, cTD )
ENDDO
aAdd( aTRs, aTDs )
ENDDO
RETURN aTRs
He obviado el 'recorte' de la TABLE, creo que es lo suficientemente sencillo.
Cosas que no tiene en cuenta: rowspans, colspans, y que los títulos y footers estén marcados con th, tfoot, cosas que pueden complicar el asunto, pero creo que salvo eso se debería comer todo lo que pertenezca a tr/td.