Toon posts:

[JS] Nesting correctie

Pagina: 1
Acties:
  • 115 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Neem onderstaande code, waarin de B en U tags ranzig genest zijn.

code:
1
2
3
4
5
6
7
8
9
<DIV>
  <B>
    bold
    <U>
      bold_underline
    </B>
    underline
  </U>
</DIV>


Wanneer ik het document nu doorloop merk ik dat "underline" zowel een child is van DIV als van U. Nu krijg ik dus problemen met mijn nesting parser. Is hier een oplossing voor of is dit een gebrek? Moet ik mijn eigen huidige parser blijven gebruiken (tokenizer) of is er een oplossing?

  • coubertin119
  • Registratie: Augustus 2002
  • Laatst online: 15-05 15:12
Als je alle tags op een stack gooit, en checkt of de laatst-geopende tag ook de eerst-gesloten tag is enzovoorts, lukt het toch? Bovendien hoef je op een pagina helemaal geen <b> en <u> te mogen hebben ;).

Skat! Skat! Skat!


  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 25-02 11:17

Clay

cookie erbij?

Als ik een parser was zou ik bij het tegenkomen van die </b> besluiten de <u> te sluiten. De </u> een endje verderop zou ik dan wegmikken. Maar wat doet je parser er nu mee dan?

Instagram | Flickr | "Let my music become battle cries" - Frédéric Chopin


Verwijderd

Topicstarter
Dat is dus precies wat mijn parser doet, hele bestand doorlopen, teken voor teken en analyseren (zonder DOM dus), nu wil ik het mét DOM doen. Dat U en B niet gebruikt mogen worden is onbelangrijk...
Ik ben er inmiddels wel achter dat een vergelijking tussen de twee referenties naar de verwijzingen een TRUE oplevert. Nu kan ik dus van alle Nodes dus een Array bijhouden en controleren of hij al gebruikt is, zo ja, dan moet hij genegeerd worden...

Verwijderd

Topicstarter
Clay:

Mijn parser doorloopt een Node en doorloopt alle Childnodes. Als een childnode ook children heeft dan een recursieve functie... Hij analyseert dus een Node. Maar wanneer je ranzige HTML laad, is de Node niet meer lekker. Sommige elementen hebben hetzelfde Child :?
Mijn parser moet de nesting van HTML corrigeren, nu heb ik een teken-voor-teken parser en die doet het, ik wil alleen kijken of het ook met DOM kan. Die parser is namelijk niet super snel (1 sec voor 75 Kb)...

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Waarom gebruik je je eigen parser eigenlijk? Waarom laat je de browser dat niet lekker uitzoeken? :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Verwijderd

Topicstarter
Omdat klanten XHTML willen. Browser voor mobiele telefoons hebben niet de resources om Nesting te corrigeren enz enz enz...
En het staat gewoon leuk als je Editor XHTML produceert en niet die ranzige zooi van MS...
Mijn eigen parser werkt nu op zich perfect, maar als ie met DOM zou werken zou dat natuurlijk helemaal mooi zijn...

Voor een voorbeeldje:

www.nextavenue.com/javascript/xhtml_dom/

edit:

Dit voorbeeldje is wel mijn parser, maar niet mijn parser die perfect werkt, dit is een beginnetje van een DOM parser...
Alleen zoals ik al eerder aangaf gaat het doorlopen van een Node niet altijd even lekker...


Moet je even op de knop Query Verzenden klikken (geen value attr :)) en vergelijk dan de HTML eens in de textbox, met die van het Frame...

Nu weet je waarom :)

[ Voor 18% gewijzigd door Verwijderd op 25-02-2004 19:53 ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-04 17:38
Ik zou het zo (laten) doen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
doorwerken van pagina:

1.  DIV  -o>  <DIV>

2.  B    -o>  <B>

3.  U    -o>  <U>

4.  /B
   ! Laatst geopende is U, dus eerst U sluiten en moet blijkbaar nog doorlopen, 
   want is nog niet afgesloten dus

         -o>  </U></B><U>

5. /U    -o>  </U>

6. /DIV  -o> </DIV>

[ Voor 16% gewijzigd door r0bert op 25-02-2004 20:50 ]


Verwijderd

Topicstarter
Ik heb geen problemen met het algoritme, maar puur met IE...

code:
1
2
3
4
5
6
7
8
9
<div>
  <b>
    foo1
    <u>
      foo2
    </b>
    foo3
  </u>
<div>


In bovenstaand voorbeeld is "foo3" zowel een Child van U als van DIV, iets wat niet de bedoeling is. Ik wil dus benadrukken dat ik het nestingalgoritme wel heb, maar dat IE een puinhoop maakt tijdens het inladen van een document...
Iemand een oplossing hiervoor? "foo3" zou namelijk alleen een Child moeten zijn van U

  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-04 17:38
Zeker weten waar het element van is kun je dus niet, maar waar wil je dan vanuit gaan? bijv. :?
  • Het eerste element waar de tag in geopend wordt is de parent
  • Het diepst geneste gedeelte van de tag is waar het element child van is
  • Het minste diep geneste gedeelte van de tag is waar het element child van is
Ik ben het trouwens wél eens met de oplossing dat het element van beiden child is, want dat is naar mijn idee ook zo. Er verschijnt een
code:
1
2
3
4
(DIV)
 vette tekst (B)
 vet en onderstreept  (U + B)
 onderstreepte tekst  (U)

Het klopt dus niet om te zeggen dat .. Het klopt dus niet dat U slechts een child van B is, want de onderstreepte tekst is geen child van B maar duidelijk alleen van de DIV. Weet je dus zeker dat je ervan uit moet gaan dat U child van B is, en niet gewoon zoals IE zegt van beiden?

Als je U dus alleen als child van B zou zien, zou de onderstreepte tekst, gewone tekst worden.. Hoe weet je dat dat de bedoeling is?

[ Voor 52% gewijzigd door r0bert op 25-02-2004 21:15 ]


Verwijderd

Topicstarter
Kijk nu komen we ergens...

Het diepst geneste gedeelte van de tag is waar het element child van is

In bovenstaand voorbeeld moet "foo3" enkel en alleen een Child zijn van U, nu heb ik een oplossing. Het enige probleem: het aantal berekeningen stijgt exponentieel...

DIV.ChildNodes[2] == U.ChildNodes[2]

Die vergelijking levert true op, dit geeft dus aan dat het slechts een verwijzing is naar de Node. Nu dacht ik: dan houd ik gewoon bij welke Nodes al geweest zijn:

code:
1
2
3
4
5
6
    for (var i = 0; i < this.oaNodesParsed.length; i++) {
      if (this.oaNodesParsed[i] == node) {
        return;
      }
    }
    this.oaNodesParsed[this.oaNodesParsed.length] = node;


Maar zoals je kan nagaan, loopt dit erg snel uit de hand...

Ik zal zo even een voorbeeldje op internet plaatsen, ik Edit de post zo... brb

Verwijderd

Topicstarter
Oeps foutje...

Ik verwacht dit:

Het eerste element waar de tag in geopend wordt is de parent

Kriebel ik snap er nu zelf even niets meer van :? 8)7 :?
Ik denk dat ik er maar mee moet ophouden... :s

www.nextavenue.com/javascript/got/

  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-04 17:38
Ik weet niet of ik je goed begrijp, maar is zoiets een oplossing
  • Objecten doorlopen en alle open objecten bijhouden
  • Aan ieder object wat geparsed is een attribuut 'isParsed' met waarde true hangen
  • Kijken of element in de array van verkeerd geneste elementen bestaat, zo ja, kijken wat er met element moet gebeuren (bijv verwijderen)
  • Anders als een element niet goed genest is, deze in een aparte Array gooien
  • Als isParsed voor een element true is, betekend dat dat deze al geparsed is en dus verwijderd kan worden
dus nu krijg je
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
doorwerken van pagina:

1.  DIV  -o>  <DIV>

2.  B    -o>  <B>

3.  U    -o>  <U>

4.  /B
   ! U is de laatst geopende en niet B, dus nesting klopt niet.
   U in Array 'arrFoutGenest'gooien en vervolgens sluiten

         -o>  </U></B>

5. /U
   ! Bij controleren of element in 'arrFoutGenest' zit, is het geval
     en hier staat het attribuut isParsed op true, dus het element is
     al geparsed en kan verwijderd worden
     -o> 

6. /DIV  -o> </DIV>


edit: oh oei, ff checken of daar iets op te vinden is

[ Voor 179% gewijzigd door r0bert op 25-02-2004 21:39 ]


Verwijderd

Topicstarter
isParsed attribuut... geniaal, kriebel, waarom ben ik daar niet zelf op gekomen? |:( |:( |:(


_/-\o_

Tevroeg gejuicht :D

De Nodes die de problemen geven zijn van type 3, oftewel Text nodes en die eten geen attribuut...

Node.isParded wil dus niet...

[ Voor 42% gewijzigd door Verwijderd op 25-02-2004 21:35 ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-04 17:38
[knip.. hier stond onzin bij nader inzien onzin ;) ]

[ Voor 102% gewijzigd door r0bert op 25-02-2004 22:10 ]


  • Johnny
  • Registratie: December 2001
  • Laatst online: 15-05 23:15

Johnny

ondergewaardeerde internetguru

Dus als ik het goed begrijp maak je en parser die ransig MSHTML dat waarschijnlijk afkomstig is uit een CMS met MSIE omzetten naar XHTML?

Je kunt dan ook gewoon de code die jij gaf laten omzetten naar dit:
code:
1
2
3
4
5
6
7
8
9
<div>
  <span style="font-weight: bold;">
    bold
    <span style="text-decoration: underline;">
      bold_underline
    </span>
    underline
  </span>
</div>


In dat geval hoef je je niet druk te maken over parsen en nesten, simpelweg search&replace en er komt altijd valid XHTML uit.

Maar de laatste "underline" wordt dan wel vet

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Jorgen Horstink:
Omdat klanten XHTML willen. Browser voor mobiele telefoons hebben niet de resources om Nesting te corrigeren enz enz enz...
Je wilt dat dus on-the-fly doen op het moment dat de pagina gerenderd wordt? Waar komt die 'brakke' html dan vandaan? Uit een CMS ofzo? Want dan kun je het beter doen op het moment dat de html opgeslagen wordt. Iets dergelijks doe ik ook in ons CMS; op het moment dat de HTML opgeslagen wordt wordt het 'schoongeveegd'. Dit is een eitje als je gewoon de DOM tree die IE aanmaakt (op basis van mshtml) doorloopt en vervolgens daarvan xhtml bakt.

Als ik het niet begrijp moet je me even uitleggen waar en wanneer je je eigen parser dan precies in wilt zetten, want dat pas bij de client doen op het moment van opvragen van de html is uberhaupt bad practice, imho :)

Of je vindt het gewoon leuk om een parser te schrijven, dat kan natuurlijk ook :P

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-04 17:38
Ik heb nog steeds het idee dat er iets niet klopt aan het hele verhaal hierboven.

De output dat U bij én B én DIV wordt gerekend, is eigenlijk gewoon goed ja? Want de output die je daarna krijgt, is dezelfde als de gebruiker bij de invoer heeft gezien, en wat dus blijkbaar zijn bedoeling was..

Dan ben je toch verkeerd bezig om de U tag ineens alleen bij de DIV te laten horen? Want dan krijgt de gebruiker een andere opmaak in zijn output dan in zijn input bedoelt was.. Toch :?

Verwijderd

r0bert schreef op 26 februari 2004 @ 17:07:
Dan ben je toch verkeerd bezig om de U tag ineens alleen bij de DIV te laten horen? Want dan krijgt de gebruiker een andere opmaak in zijn output dan in zijn input bedoelt was.. Toch :?
Nouja, verkeerd bezig...het zou misschien netter zijn om de gebruiker een waarschuwing te geven en eventueel verschillende opties van valide XHTML waar 'ie uit zou kunnen kiezen.

Verwijderd

Topicstarter
Ik zal even kort vertellen wat de DOM parser fout doet. Het probleem is dat het doorlopen van de DOM Node niet goed gaat. Wanneer de nesting verkeerd was, kan een Textnodes bij twee verschillende Parent-nodes horen. :?

De parser wordt gebruikt om de HTML die mijn Editor genereert te corrigeren (IFRAME en dan outerHTML ophalen van het documentNode). Die HTML is ranzig en moet netjes worden weergegeven. Nu zijn er twee aanpakken:

1.) Een eigen parser. Haal de HTML op en maak eerst een Tokenizer die de string parsed en opsplitst in Nodes. Een grote Array dus. (Dit is nog een lastige klus: <b onclick="4<5"> let op die 4<5). Wanneer je de Array heb kan je een nesting correctie algoritme toepassen. Zo heb je dus een eigen complete parser gemaakt die niet op DOM gebaseerd is. Zo'n parser heb ik nu, haalt 98% van alle fouten eruit zonder het design te verneuken.

2.) Een DOM parser. Je haal de start-node op: window.frames["editor"].document oid
Vervolgens krijg je een functie iets als: (pseudo code)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var sRet = "";
function _appendNodeXHTML(Node) {
  for (i = 0; i < Node.childNodes.length; i++) {
  switch (Node.nodeType) {
    case 1: // Node
       sRet += "<" + Node.nodeName + ">"
       if (node.hasChildNodes) {
         _appendNodeXHTML(Node.childNodes[i])
       }
       sRet += "</" + Node.nodeName + ">"
    case 3: // Text
       sRet += Node.nodeValue;
  }
  }
}


Moet nu eten, zal zo mijn post afmaken lees eerst deze code maar :D

[ Voor 14% gewijzigd door Verwijderd op 26-02-2004 18:22 ]


Verwijderd

Topicstarter
Johnny schreef op 25 februari 2004 @ 23:19:
Dus als ik het goed ... wordt dan wel vet[/sub]
Dit kan niet wanneer er een CSS attribuut is gedefineerd voor alle B tags. Dit probleem is niet eenvoudig op te lossen.

Verwijderd

Topicstarter
drm schreef op 26 februari 2004 @ 09:32:
[...]
...Dit is een eitje als je gewoon de DOM tree die IE aanmaakt (op basis van mshtml) doorloopt en vervolgens daarvan xhtml bakt....
Mijn hele post draait hierom. Het is helemaal niet zo'n eitje. Want het doorlopen van die DOM tree gaat niet goed wanneer de nesting niet goed is. Neem de proef op de som.

code:
1
2
3
4
5
6
7
8
9
<body>
  <b>
  foo1
  <u>
  foo2
  </b>
  foo3
  </u>
</body>


Sla het op in een HTML bestand en doorloop de DOM tree, gaat je niet lukken...
"foo3" is een Child van zowel de Body-node als van de U-node...

Verwijderd

Topicstarter
Of iets als dit:

code:
1
2
3
4
5
<table>
  <tr>
    <td>foo</td><b>Dit hoort hier niet en zorgt dat het doorlopen van de Node compleet fout gaat en zelfs voor Errors zorgt...</b>
  </tr>
</table>


Nu kan je zeggen: jah dat moeten klanten ook niet invoeren. Maar je mag er nooit vanuit gaan dat de input die je krijgt correct is...

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Hm, je snapt niet wat ik bedoel. Als ik het woord innerHTML laat vallen snap je het waarschijnlijk beter ;)

Ik vind het heel dapper dat je een complete html parser hebt geschreven, maar imho ben je dan het wiel aan het uitvinden. Je zit nota bene in een programma dat per definitie gemaakt is om die zooi te parsen, laat dat programma het dan lekker uitzoeken.

Even een voorbeeldje in elkaar geflansd:

http://gerard.yoursite.nl...Horstink/dom-to-html.html

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Verwijderd

Topicstarter
Nu word ik compleet gek. Dat is zo'n beetje precies de code die ik gebruikt heb.

http://www.nextavenue.com/javascript/got/xhtml.js

Bij mij vreet ie die code niet. I am losing it :D
Ik ga even kijken of ik een voorbeeld kan krijgen waarbij het fout gaat...

Verwijderd

Topicstarter
Gelukkig, ik dacht al, als ie het doet ben ik gek.

Vervang:

code:
1
2
3
4
5
6
7
8
9
10
11
var someHtml = '\
<p>             \
  <b>           \
  foo1          \
  <u>           \
  foo2          \
  </b>          \
  foo3          \
  </u>          \
</p>            \
';


Maar eens door:

code:
1
var someHtml = '<p><b>foo1<u>foo2</b>foo3</u></p>';


Happy bug tracing :D

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Ok, je hebt gelijk 7(8)7

Dat is dus niets minder dan een IE bug. Firefox heeft er overigens geen enkele moeite mee...

Even kijken of ik een oplossing kan verzinnen.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Verwijderd

Topicstarter
Zoals ik zeg, die textnode "Foo3" is een Child van zowel de P tag als van de U tag. Daarom wordt hij 2 keer in het resultaat gezet. Mozilla doet het inderdaad ook perfect. Het is zoals je zelf al aangaf een IE bug, maar aangezien mijn Editor voor IE bedoeld is...
Eindelijk snapt iemand mijn probleem :D

Yoehoe :)

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Gelukkig is het ook makkelijk naar een oplossing zoeken als het probleem begrepen is :P

Hou een array bij van referenties aan de al geparste nodes. Dan kun je de nodes die al geweest zijn uitsluiten.

zie http://gerard.yoursite.nl...tink/dom-to-html-fix.html

edit:
Overigens krijg je dan wel een ander resultaat dan in Mozilla O-) maar goed, dat moet je dan maar voor lief nemen, denk ik.

IE begrijpt gelukkig wel dat het dan dezelfde textnode is (die referenties kloppen) dus dan moet je er uit komen :)

[ Voor 34% gewijzigd door drm op 26-02-2004 19:49 ]

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Verwijderd

Topicstarter
Die gedachtengang van jou had ik gisteren :D
Die "oplossing" had ik zelf ook. Ik kan maar beter mijn huidige tokenizer parser gebruiken zonder DOM, die doet het tenminste voor 99% correct zonder fouten :)
In ieder geval bedankt voor je hulp...
Waarom moet Microsoft het nou altijd verpesten :D

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Jorgen Horstink:
Die gedachtengang van jou had ik gisteren :D
Die "oplossing" had ik zelf ook. Ik kan maar beter mijn huidige tokenizer parser gebruiken zonder DOM, die doet het tenminste voor 99% correct zonder fouten :)
IE doet het ook voor 99% correct zonder fouten :+
In ieder geval bedankt voor je hulp...
Waarom moet Microsoft het nou altijd verpesten :D
* drm is reliving the Netscape 4.x age all over again :/

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz

Pagina: 1