Base_Html_Document – Eine Kooperation?
Den heutigen Tag nutze ich mal um ein wenig um Kooperation zu bitten. Ich habe da eine Idee, hab aber nicht wirklich Lust das alleine umzusetzen. Ist zwar nicht groß, aber da es danach jeder nutzen kann, kann man ja mal die Community fragen.
Also gut, ich bin gerade an zwei Projekten und bei beiden muss ich irgendwie HTML-Seiten nehmen und etwas mit ihnen machen. In dem einen Fall würde ich gerne alle Bilder raussuchen und in dem anderen alle Links und externen Files. Klingt ja ganz einfach. Die zwei Projekte sind grundunterschiedlich und haben trotzdem die gleiche Anforderung. Da möchte man doch glatt glauben, dass man nicht der einzige ist, der vor einer solchen Anforderung steht.
Jetzt würde ich gerne eine Objektrepresentation eines Html-Dokuments haben. Dort kann ich dann ganz einfach auf die syntakitischen Bestandteile zugreifen. Stelle mir auch sowas vor wie $document->getDivById('superDiv')->getJavaScriptHandler()->getOnClick()
wird also so ungefähr klar, was ich will? Bin ich der einzige mit der Anforderung? Bestimmt nicht. Auch wenn ihr es bis jetzt nicht wisst. Jetzt fragt ihr euch sicher, wenn das so einfach ist. warum macht der faule Langner das nicht selbst? Naja die Antwort ist ganz simple. Ich hätte gerne eine relativ vollständige Implementierung, also wahrscheinlich für jedes HTML-Tag auch eine Objektrepresentanz. Das kann relativ aufwendig werden, wenn man den ganzen Standard nimmt.
Mich würde es also freuen, wenn wir ein paar Entwickler sind und das umsetzen. Ich würde ein Git-Repository einrichten und loslegen. Natürlich vorher ein paar Skizzen machen und man sollte versuchen den Code dann irgendwie ins Zend Framework zurück zu spielen, da es da wunderbar reinpassen würde. Das eine Tool, das ich damit bauen will, wird selbstverständlich auch als Open Source veröffentlicht.
Moin,
das sieht mir stark nach einem Job für SimpleXML und XPath aus. Damit müsste man eine recht generische Library zusammenhacken können.
Zu dem JavaScript Teil … du möchtest nur auf das onClick Attribut des DIVs zugreifen, nicht eventuell später zugewiesene Events ermitteln, richtig? Andernfalls müsste man ja einen kompletten JS-Interpreter schreiben, was sicherlich sehr interessant, aber wenig zielführend sein dürfte 😉
Just my $0.02,
Sascha
vielleicht versteh ich dich falsch aber meinst du nicht zumindest zum groessten teil dieses hier:
http://www.phparch.com/2010/04/22/four-new-php-5-3-components-and-goutte-a-simple-web-scraper/ (speziel Goutte)
Du hattest das sogar mal selbst verlinkt (http://www.phphatesme.com/blog/aktuelles/symfony-components-2-0/).
Bis auf die Javascript Sachen scheint mir da bereits alles drin zu sein. Sollte also mindestens als Basis herdienen koennen.
Ganz provokant: Was genügt dir an den DOMDocument-Klassen in Kombination mit einem validierenden Schema denn nicht?
$document->getElementById(’superDiv‘)->getAttribute(‚onclick‘)
>> $document->getDivById(’superDiv‘)->getJavaScriptHandler()->getOnClick()
$xpath->query(‚//div[@id = „superDiv“]/@onclick‘);
Oder so ähnlich. (0;
Sehe ich wie Martin: alles schon da!
I chicer Ansatz zur einfachen Verarbeitung von XML/HTML ist FluentDOM: http://fluentdom.github.com/. Vielleicht lohnt es sich ja, hier mal rein zu schauen und es evtl. auszubauen?
Wie wärs damit?
http://simplehtmldom.sourceforge.net/
oder
http://code.google.com/p/phpquery/
oder
http://framework.zend.com/manual/en/zend.dom.query.html
oder willst du Rad neuerfinden?
Schau dir mal FluentDOM an:
http://fluentdom.github.com/docs/index.html
„FluentDOM ist a jQuery like fluent XML interface for the DOMDocument in PHP.“
Damit gehen Sachen wie:
$imageNodes = FluentDOM($xhtml)->find(‚img‘);
Nimmst du halt DOM oder XMLReader oder
– phpQuery (http://code.google.com/p/phpquery/),
– Zend_Dom (http://framework.zend.com/manual/en/zend.dom.html),
– QueryPath (http://querypath.org/),
– FluentDom (http://www.fluentdom.org) oder
– fDOMDocument (http://github.com/theseer/fDOMDocument)
Hi Nils,
ich fände ne Wrapper z.B. auf Basis von dem FluentDOM ganz spannend und wäre dabei.
Grüße
Björn
XML, XPath, XQuery, XSD, XSLT, … das wäre wohl nur noch ein Xirgendwas (vielleicht mit einem P für PHP als Suffix)
Ich halte den Ansatz für nicht sinnvoll. HTML ist eine Datenstruktur. Ich würde nicht versuchen sie direkt als direkte Objektstruktur (SimpleXML like) zu implementieren/nutzen.
Ein Zugriff wie dort beabsichtigt wäre auch nicht möglich. Die Prüfung wurden vergessen. Das könnte ja auch fehlen.
$div = $document->getDivById(’superDiv’);
if ($div) {
$jsHandler = $div->getJavaScriptHandler()->getOnClick();
…
}
Bei Xpath wird das intern erledigt – damit wird es tatsächlich ein Einzeiler.
$jsHandler = $xpath->evaluate(’string(//div[@id = „superDiv“]/@onclick)‘);
Bei FluentDOM wäre es:
$jsHandler = FluentDOM($html, ‚html‘)
->find(‚//div[@id = „superDiv“]/onclick)‘)
->attr(‚onclick‘);
Kaum sitzt man in den Bahn kommen auch schon 11 Kommentare. Danke. Jetzt nochmal vorne weg, bevor ich auf die einzelnen Punkte eingehe. Es geht mir darum eine saubere Implementierung zu schaffen, die danach jeder Verwenden kann, da ich glaube nicht alleine mit der Anforderung dazustehen. Wenn ich ein HTML-Document-Objekt zur Verfügung habe, dann nutze ich das natürlich lieber, als über DOM das zu lösen.
@Sascha: Soll eine statische Analyse des Codes sein. Also keine fertig gerenderte Seite darstellen. Also wäre toll, wenn es das könnte, aber Anforderung ist es nicht.
@Christian: Das ist eher ein Browser, oder? Aus dem Source-Code kann man aber bestimmt sehr viel rausholen und verwenden, danke für den Tipp.
@Martin, Christian, Cem: Klar würde DOMDocument genügen, aber schön ist es nicht. Ich würde wirklich gerne auf eine API zugreifen können. Es intern mit DOM zu lösen, ist natürlich absolut denkbar. Wenn es einmal sauber entwickelt wurde, müsste niemand mehr DOM verwenden für sowas.
@toby & aeckhoff: FluentDom als Basis kann gut passen. (und Toby, sag bitte nicht Bastian, dass ich’s nicht von selbst geschrieben hab).
Hi Nils, leider fehlt aufgrund einer beruflichen Veränderung die Zeit, mitzuwirken. ABer ich erinnere mich gerade an die WebTech 2010. Chris Heilmann hat sowas in der Art mit u.a. YQL umgesetzt:
http://www.wait-till-i.com/2009/01/11/adding-transcripts-to-presentations-embedded-from-slideshare-using-yql/
Grüße
Flo
Ich würde auch phpQuery empfehlen, habe damit schon ähnliche Anforderungen realisiert.
Die Lösung sollte auch externe Javascript Dateien laden, denn inline „onclick“ ist ja böse 😉 Keine Ahnung ob das die oben genannten Lösungen können.
Bin kein Javascript Experte, aber man sollte heutzutage auch an Delegations denken. Das onClick Event könnte auch „höher im Baum“ hängen und dann dort abgefangen und bearbeitet werden. Das wiederum ist aber sehr schwer herauszubekommen, weil man dazu den Javascript-Code analysieren müßte ob darin ein Pfad ist, der wichtig ist.
Was mir noch eingefallen ist waere das zetaComponents Documents Modul
http://incubator.apache.org/zetacomponents/documentation/trunk/Document/tutorial.html#xhtml
DOM wäre IMHO der richtige Weg.
Nur das Ziel ist irgendwo Quark, wer vernünftiges JS schreibt — namentlich behavioural bzw. unobtrusive JS — wird keine Inline-Events mehr notieren. Schon mit Bibliotheken wird das mittlerweile so einfach, dass das auch Standrad werden wird, JS von aussen aufzupropfen. Ergo keine Chance für Deinen Parser. Da müsste dann schon ein Javascript-Interpreter ran, der womöglich noch jQuery oder andere Librarys verarbeiten kann.
http://24ways.org/2006/writing-responsible-javascript
http://aktuell.de.selfhtml.org/weblog/javascript-einsatz
Hab mir so was in der Art gebaut. Da ich das Programmieren an der Uni mit Java gelernt habe und den dortigen Ansatz von „Swing“ ganz gut finde (ja ok steinigt mich meinetwegen).
Dieser Ansatz der GUI-Programmierung ist jedoch mittels PHP/HTML nicht realisierbar, da HTML keine dynamischen Events feuern kann. Eventsteuerung über HTML-Attribute ist zwar möglich, aber ein zu starres Konzept.
Hinzu kommt, dass durch die eingebaute Funktionalität (a, input, checkbox, …) es zu unkontrollierbarem und vor allem nicht mockbarem Verhalten kommt.
Konsequenterweise muss man dann sagen, dass somit eine GUI-Programmierung mit PHP in meinen Augen eigentlich kein Sinn macht. Was übrig bleibt, ist eine objektorientierte Erzeugung der Ausgabe, die es ermöglicht, diese Ausgabe unterschiedlich zu formattieren:
$paragraph = new Paragraph();
$paragraph->setClass(„center“);
$link = new Link(„/index“, „Startseite“);
$link->setId(„meinLink“);
$link->setTarget(„_blank“);
$paragraph->addComponent($link);
$paragraph->toString();
$paragraph->toHTML();
$paragraph->toHTML5();
$paragraph->toJson();
$paragraph->toHTMLMail();
…
Es bietet viele Vorteile. Klar ist es in erster Linie erstmal mehr Aufwand. Ob sich so was lohnt muss jeder selbst wissen.
mir wär es zu viel Aufwand 😉