mit NSXMLParser Tabelle parsen und als TableView abbilden

  • mit NSXMLParser Tabelle parsen und als TableView abbilden

    Hallo Freunde der Mac/iOS Programmierung,

    nachdem ich nun den halben Tag im Internet verzweifelt und erfolglos herumgesucht habe dachte ich, ich mach mal einen neuen Thread hier auf.

    Ich Entwickle eine iPhone App wo ich von einer HTML Seite eine Tabelle auslesen und in einem TableView abbilden soll.
    Nun habe ich verstanden das eine Tabelle in HTML mit sog. "tr" Tags abgebildet wird.

    Dies sieht dann ungefähr so aus:

    Quellcode

    1. <table border="0" width="100%" id="table2" cellpadding="0" height="28" cellspacing="0">
    2. <tr>
    3. <td height="22" width="1%" class=ListeUngerade></td>
    4. <td height="22" width ="*" class=ListeUngerade>170504 St.Pölten-Stadt</td>
    5. <td height="22" width="28%" class=ListeUngerade>B1 Alarm2</td>
    6. <td height="22" width="20%" class=ListeUngerade>22.01.2012 < 1 std.</td>
    7. </tr>
    8. <tr>
    9. <td height="22" width="1%" class=ListeGerade></td>
    10. <td height="22" width ="*" class=ListeGerade>100617 Trandorf</td>
    11. <td height="22" width="28%" class=ListeGerade>T1 Alarm3</td>
    12. <td height="22" width="20%" class=ListeGerade>22.01.2012 < 1 std.</td>
    13. </tr
    14. ><tr>
    15. <td height="22" width="1%" class=ListeUngerade></td>
    16. <td height="22" width ="*" class=ListeUngerade>040207 Groß-Enzersdorf</td>
    17. <td height="22" width="28%" class=ListeUngerade>B1 Alarm4</td>
    18. <td height="22" width="20%" class=ListeUngerade>22.01.2012 ~ 4 std.</td>
    19. </tr>
    20. </table>
    Alles anzeigen



    Mit diesem Code hol ich mir das ganze in den Parser:

    Quellcode

    1. NSXMLParser* parser = [[NSXMLParser alloc] initWithContentsOfURL:url];


    So, soweit so gut. Ich habe verstanden das das NSXMLParser Objekt ein paar delegates hat die ich implementieren muss.
    Wie bekomme ich aber die Texte der einzelnen Tabellen wie z.b. 170504 St.Pölten-Stadt, B1 Alarm2, 22.01.2012 < 1 std. usw. herausgeparst damit ich damit mein TableView befühlen kann.
    Ok ich könnte das ganze in einem String umwandeln und dann mühsam einzeln rausfrimeln.
    Aber ich denke mir das muss doch irgendwie einfacher gehen aus dem NSXMLParser heraus.


    Ich freue mich schon auf eure Antworten :-)
  • Hallo,

    das wichtigste ist, dass Dein Dokument unbedingt XHTML sein muss. Ist es das? NSXMLParser kommt nicht mit echten HTML Dokumenten klar (die z.B. <br> oder <img src="foo"> ) enthalten. Solche Dokument musst du mit z.B. libxml2 bearbeiteten.

    Abgesehen davon verstehe ich Deine Frage nicht. Was hast Du probiert? Was hat funktioniert? Was verstehst Du nicht?

    Alex
    The only thing that really worried me was the ether.
  • Hallo,

    also die Seite ist ein HTML Dokument.
    Dies ist der source Code davon. es beinhaltet eine Tabelle

    HTML-Quellcode

    1. <html><head><meta http-equiv="Content-Language" content="de"><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><link rel="stylesheet" href="/stylesheet.css" type="text/css"><title>Alarme Niederoesterreich</title></head><body class="ListeEng" topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0" marginwidth="0" marginheight="0">
    2. <table border="1" width="100%" id="table2" cellpadding="0" height="28" cellspacing="0">
    3. <tr><td height="22" width="1%" class=ListeUngerade></td><td height="22" width ="*" class=ListeUngerade>170504 St.Pölten-Stadt</td><td height="22" width="28%" class=ListeUngerade>Alarm1</td><td height="22" width="20%" class=ListeUngerade>22.01.2012 < 1 std.</td></tr><tr><td height="22" width="1%" class=ListeGerade></td><td height="22" width ="*" class=ListeGerade>100617 Trandorf</td><td height="22" width="28%" class=ListeGerade>Alarm2</td><td height="22" width="20%" class=ListeGerade>22.01.2012 < 1 std.</td></tr><tr><td height="22" width="1%" class=ListeUngerade></td><td height="22" width ="*" class=ListeUngerade>040207 Groß-Enzersdorf</td><td height="22" width="28%" class=ListeUngerade>Alarm3 </td><td height="22" width="20%" class=ListeUngerade>22.01.2012 ~ 4 std.</td></tr> </table></body></html>


    ich möchte wissen wie ich am einfachsten die Texte der Tabelle in ein NSArray oder NSString bekomme.
    Dieser Code sieht im Browser so aus: pastehtml.com/view/blmlt5qk4.html

    Ich will mit den darin enthaltenen Texten ein TableView in einer iPhone/iPad App füllen.
  • Naja, schau Dir mal an, was die Delegates "didStartElement" und "didEndElement" liefern

    Noch ein Tip: foundCharacters kann mehrmals aufgerufen werden (Also wenn der Text "St. Pölten" ist, kann der Delegate durchaus drei mal aufgerufen werden, z.B. mit "St. P", "ö" und "lten")

    Gruss

    Alex
    The only thing that really worried me was the ether.
  • ok aber ich weiss ja vorher nicht das der Text St. Pölten ist. Wie soll ich dann nach dem Text suchen?


    Wie kann ich mir die didStartElement: deleages vorstellen?
    Wird dieses Delegate bei jedem tag aufgerufen? Falls ja wie lese ich dann den den text zwischen den tags aus?

  • stickdog schrieb:

    below schrieb:

    Schon TFM gelesen?
    schon gelesen aber leider auch keine Möglichkeit gefunden wie ich eine HTML Tabelle parse.
    Dieses Dokument bezieht sich nur auf normale XML Files wo Elemente verschachtelt und mit tags markiert sind.


    Was ist Dein Problem? Hast Du schon Code geschrieben und ausprobiert? <table>, <td> und <tr> sind ganz normale XML Tags (vorausgesetzt, das HTML Document lässt sich als XML Parsen, siehe oben)

    Alex
    The only thing that really worried me was the ether.
  • Folgendes delegate

    Quellcode

    1. - (void)parser:(NSXMLParser *)parser
    2. didStartElement:(NSString *)elementName
    3. namespaceURI:(NSString *)namespaceURI
    4. qualifiedName:(NSString *) qName
    5. attributes:(NSDictionary *) attributeDict
    6. {
    7. NSLog((@"elementName = %@ -- %s [Line %d] "),elementName, __PRETTY_FUNCTION__, __LINE__);
    8. }



    spuckt folgendes aus:

    Quellcode

    1. 2012-01-23 13:21:42.907 URLloader[531:f803] LoaderView did Load -[LoaderViewController viewDidLoad] [Line 44]
    2. 2012-01-23 13:21:43.158 URLloader[531:f803] elementName = html -- -[LoaderViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:] [Line 61]
    3. 2012-01-23 13:21:43.158 URLloader[531:f803]
    4. 2012-01-23 13:21:43.159 URLloader[531:f803] elementName = head -- -[LoaderViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:] [Line 61]
    5. 2012-01-23 13:21:43.160 URLloader[531:f803]
    6. 2012-01-23 13:21:43.161 URLloader[531:f803] elementName = meta -- -[LoaderViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:] [Line 61]
    7. 2012-01-23 13:21:43.161 URLloader[531:f803]
    8. 2012-01-23 13:21:43.162 URLloader[531:f803] elementName = meta -- -[LoaderViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:] [Line 61]
    9. 2012-01-23 13:21:43.163 URLloader[531:f803]
    10. 2012-01-23 13:21:43.165 URLloader[531:f803] elementName = link -- -[LoaderViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:] [Line 61]
    11. 2012-01-23 13:21:43.165 URLloader[531:f803]
    12. 2012-01-23 13:21:43.166 URLloader[531:f803] elementName = title -- -[LoaderViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:] [Line 61]
    13. 2012-01-23 13:21:43.167 URLloader[531:f803] Zeige eingesetzte Feuerwehren in N
    Alles anzeigen



    bei oben angegebenen XML File.
    Das Problem ist das ich entweder komplett auf dem Schlauch stehe oder du verschwendest meine Zeit mit Käse labern.
  • Das sieht doch gut aus!

    Und danach hört der Output auf einmal auf? Ich hätte hier jetzt erwartet, dass auch die table, td und tr Elemente irgendwann ausgespuckt werden.

    Jetzt würde ich mal den Fehler Delegate implementieren, und das HTML File in (erinnere Dich an meinen ersten Post) durch xmllint jagen, im Terminal:

    xmllint /derPfad/deineDatei.html

    Wie gesagt, falls die Datei nicht als XML verarbeitet werden kann (also XHTML ist), kannst Du mit NSXMLParser nichts anfangen und musst entweder den Input XML kompatibel machen, oder einen anderen Parser nehmen.

    Ich denke, wir jeden hier nicht mehr aneinander vorbei :D

    Alex
    The only thing that really worried me was the ether.
  • aaah, ich bekomme einen Fehler beim parsen.

    Quellcode

    1. 2012-01-23 14:11:40.473 URLloader[643:f803] parseError = The operation couldn’t be completed. (NSXMLParserErrorDomain error 9.) Failure Reson = (null) RecoverySuggestion = (null) -- -[LoaderViewController parser:parseErrorOccurred:] [Line 73]


    Ich weiss zwar noch nicht warum aber jetzt weiss ich warum ich die tb, tr tags nicht bekomme.
  • stickdog schrieb:

    was ist xmllint? das scheint irgendein Konsolen Befehl zu sein. Was soll ich damit machen?
    Ich will das HTML File nicht ändern sondern wissen wie ich die HTML Tabelle einlesen kann.


    1) Ja, xmllint ist ein Konsolenbefehl. Damit kannst Du prüfen, ob die HTML Datei valides XML ist

    2) Jetzt muss ich doch mal ernsthaft Fragen: Liest Du meine Posts nicht? Schon in meiner ersten Antwort habe ich gesagt, dass deine HTML Datei valides XML sein muss, denn nicht jede HTML Datei ist valides XML! NSXMLParser ist ein XML Parser. Er kann nur XML parsen, dazu gehört die echte Untermenge von HTML Dateien, die valides XML sind.

    Wenn Du jede HTML Datei parsen möchtest, also auch die, die kein valides XML sind, dann brauchst Du einen Parser, der das kann, wie zum Beispiel libxml2

    Du musst jetzt erst einmal herausfinden:

    a) Ob die Datei, die Du aktuell parsen willst valides XML ist
    b) Ob das auch im Betrieb immer so bleibt.

    Alex
    The only thing that really worried me was the ether.
  • stickdog schrieb:

    Also es bleibt schon immer so.
    Aber mir ist es egal ob Ichs als XML Parse oder irgendwie anders.
    Ich will nur diese Daten in der HTML Tabelle auslesen und in ein NSArray speichern.

    Gibt's da nichts anderes für HTTP Tabellen?


    Wenn Du HTML (nicht HTTP, das ist das Übertragungsprotokol) parsen willst, kann ich Dir nur libxml2 empfehlen. Das ist aber nicht so einfach, sondern pures C. Du kannst auch mal auf Google Code oder github nach einem Objektive-C HTML Parser zucken.

    Die Alternative ist, dass ganze mit NSScanner oder regulären Ausdrücken zu machen. Hängt jetzt von Deiner Erfahrung und der Komplexität der Dokumente ab

    Alex
    The only thing that really worried me was the ether.