javascript geneste gelijknamige tags vangen

Pagina: 1
Acties:

  • b19a
  • Registratie: September 2002
  • Niet online
ik ben bezig om in javascript een functie te schrijven die als invoer html pakt en als uitvoer een dom-object teruggeeft. Ik heb het script zover werkend dat bijna alles goed gaat. Het enige wat nog een probleem is zijn geneste gelijknamige tags. Ik wil het proces als volgt inrichten: de firstpass pak ik alle root-items, 2e ronde sub-items... etc tot ze geweest zijn. Hoe en wat doet er niet veel toe, ik probeer een replace op te stellen die de volgende html transformeert:
code:
1
2
3
<div>
    <div>tekst</div>
</div>
Wat moet worden:
code:
1
2
3
<div.1>
    <div>tekst</div>
</div.1>


Probleem is, is dat de volgende invoer:
code:
1
2
3
4
5
6
<div>
    <div></div>
</div>
<div>
    <div></div>
</div>
Dit moet namelijk vervangen worden door:
code:
1
2
3
4
5
6
<div.1>
    <div></div>
</div.1>
<div.1>
    <div></div>
</div.1>


Zodra dit namelijk eenmaal gebeurt is dan kan ik de string splitsen zodat elk element 1 (root) tag bevat. Bij het doornemen van alle elementen stuur ik vervolgens de functie weer aan met alle html binnen het element. Op die manier verwerk ik dus alle html in de invoer.

Punt is is dat je het volgens mij niet met 1 replace kunt opvangen. Zoals je ziet moet deze namelijk alleen de root-tags gaan vervangen en sub-tags ongemoeid laten.

Ik heb bijvoorbeeld de volgende js:
code:
1
text = text.replace(/<(\S+)([^>]*?)>(.+?)<\/\1>/g, function(a0,a1,a2,a3){return'<'+a1+a2+'.1>'+ a3 +'</'+a1+'.1>';});
Helaas gaat dit al bij 1 gelijknamige geneste tag de mist in. Hoe zou ik mijn functie kunnen optimaliseren?

[ Voor 13% gewijzigd door b19a op 09-12-2004 17:57 . Reden: bug ]


  • BtM909
  • Registratie: Juni 2000
  • Niet online

BtM909

Watch out Guys...

Volgens mij kan dat niet met 1 RegEx, maar ik snap niet helemaal wat je wilt retourneren :?

Kan je daar niet via DOM alleen de hoofdnodes aanpassen / vervangen / whatever (waarbij je de child-nodes dus met rust laat)?

Ace of Base vs Charli XCX - All That She Boom Claps (RMT) | Clean Bandit vs Galantis - I'd Rather Be You (RMT)
You've moved up on my notch-list. You have 1 notch
I have a black belt in Kung Flu.


  • b19a
  • Registratie: September 2002
  • Niet online
BtM909 schreef op donderdag 09 december 2004 @ 18:08:
Volgens mij kan dat niet met 1 RegEx, maar ik snap niet helemaal wat je wilt retourneren :?
Vergeet mijn inleidende verhaaltje dan maar, zie code-voorbeeld van wat ik graag voor elkaar wil krijgen.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Waarom wil je het met een regexp doen en loop je niet gewoon de DOM-tree door?
Met een enkele reguliere expressie gaat je dit niet lukken, ik zou dan minimaal stackbased gaan werken...

Intentionally left blank


  • b19a
  • Registratie: September 2002
  • Niet online
crisp schreef op donderdag 09 december 2004 @ 18:46:
Waarom wil je het met een regexp doen en loop je niet gewoon de DOM-tree door?
Met een enkele reguliere expressie gaat je dit niet lukken, ik zou dan minimaal stackbased gaan werken...
Omdat ik geen dom-tree aangeleverd krijg. Ik heb een scriptje gemaakt wat van de server html aanvraagt in een string. Deze string wil ik vervolgens omzetten naar een DOM-tree. Ik heb nog geen scripts daarvoor gezien, of ben ik dom en is er een makkelijkere oplossing?

Dit is de code die het nu voor me doet:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    parse.htmlToDom = function(text)
    {
        var text,matches,node;
    
        if(text==undefined)
            return document.createTextNode('');
        
        // do some tricks for me :)
        text = text.replace(/<([\S][^>]+?)([^\/>]*?)\/>/g, '<[]><$1$2/><[]>');
        text = text.replace(/<(\S+)([^>]*?)>(.+?)<\/\1>/g, 
        text = text.split(/<\\[\]>/g);
        
        var out = document.createElement('span');
    
        for(var part=0;part<text.length;part++)
        {
            if(text[part].match(/<(\S+)([^>]*?)>(.+?)<\/\1>/))
            {   
                matches=text[part].match(/<(\S+)([^>]*?)>(.+?)<\/\1>/)

                // create node and add text
                node = document.createElement(matches[1]);
                node.appendChild(parse.htmlToDom(matches[3]));

                // check all attributes
                //node = parse.htmlAttributes(node,matches[2]);
        
                // add it
                out.appendChild(node);
            }
            else if(text[part].match(/<(\S+)([^>]*?)\/>/))
            {   
                matches=text[part].match(/<(\S+)([^>]*?)\/>/);
                
                // create node
                node = document.createElement(matches[1]);

                // check all attributes
                //node = parse.htmlAttributes(node,matches[2]);
            
                // add it
                out.appendChild(node);
            }
            else
            {
                // it's text... leave it that way
                out.appendChild(document.createTextNode(text[part]));
            }
        }
    
        return out;
    }
(php-highlighter, gewone js code)

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

Clay

cookie erbij?

anders stop je het toch met innerHTML in een htmlElement? :P heb je wel een dom. D'r is ook een nettere manier voor die (zonder innerHTML) geheel volgens de standaard werkt, maar dat snapt IE natuurlijk niet. ;)

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


  • Annie
  • Registratie: Juni 1999
  • Laatst online: 25-11-2021

Annie

amateur megalomaan

BoukeHaarsma schreef op donderdag 09 december 2004 @ 18:56:
Dit is de code die het nu voor me doet:
[knip]
offtopic:
Beetje zinloos commentaar in je code, vind je ook niet?

Today's subliminal thought is:


  • b19a
  • Registratie: September 2002
  • Niet online
Clay schreef op donderdag 09 december 2004 @ 19:23:
anders stop je het toch met innerHTML in een htmlElement? :P heb je wel een dom. D'r is ook een nettere manier voor die (zonder innerHTML) geheel volgens de standaard werkt, maar dat snapt IE natuurlijk niet. ;)
Innerhtml begin ik niet aan... nu ik eenmaal DOM werk wil ik DOM blijven ;).

  • b19a
  • Registratie: September 2002
  • Niet online
Goed, ik zal het probleem wel wat eenvoudiger stellen. Ik wil de volgende transformaties uitvoeren op de string die ik binnen krijg:

code:
1
2
3
<div>
    <div>tekst</div>
</div>
Wat moet worden:
code:
1
2
3
<div.1>
    <div>tekst</div>
</div.1>


Probleem is, is dat de volgende invoer:
code:
1
2
3
4
5
6
<div>
    <div></div>
</div>
<div>
    <div></div>
</div>
Dit moet namelijk vervangen worden door:
code:
1
2
3
4
5
6
<div.1>
    <div></div>
</div.1>
<div.1>
    <div></div>
</div.1>

  • b19a
  • Registratie: September 2002
  • Niet online
Geloof dat m'n vraag te moeilijk is... dan maar innerhtml...

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

BoukeHaarsma schreef op zaterdag 11 december 2004 @ 18:25:
Geloof dat m'n vraag te moeilijk is... dan maar innerhtml...
Je vraag is niet te moeilijk, enkel is het niet mogelijk met een enkele reguliere expressie aangezien reguliere expressies in javascript geen recursie ondersteunen.

Intentionally left blank


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

Clay

cookie erbij?

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<html>
    <head>
    <title> Parse </title>
    <script type="text/javascript">
    
    window.onload = function() {
        var html = document.body.innerHTML;
        var level = 0;

        var parsed = html.replace(/<[^>]+>/g, function($1){
            var tag;
            if(/<\//.test($1)) {
                tag = $1.replace(/>/, '.'+ level-- +'>');
            } else {
                tag = $1.replace(/>/, '.'+ ++level +'>');
            }   return tag;
        });

        alert(parsed);
    }

    </script>
</head>
<body>
    <div>
        <div>1</div>
        <div>2</div>
    </div>
    <div>
        <div>3</div>
        <div>4</div>
    </div>
</body>
</html>


Lijkt me volledig naar wens overhoop te halen.
Geloof dat m'n vraag te moeilijk is...
imo mag je dat soort aannames lekker voor je houden :) heeft niemand wat aan namelijk.

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


  • b19a
  • Registratie: September 2002
  • Niet online
Bedankt Clay, werkt super! Nogmaals mijn dank _/-\o_. Dat de oplossing zo simpel kan zijn :+. Probleem is nog dat firefox de fout ingaat bij dit
code:
1
2
3
4
5
6
7
8
    <div>
        <div>1</div>
        <div>2</div>
    </div>
    <div>
        <div><img /></div>
        <div>4</div>
    </div>
<img /> wordt omgezet naar <img> (doe maar 's alert(html);). Het script zal vanaf daar vastlopen omdat je het niet recursief kunt opstellen. Zolang de aanvoer maar goed is zal het wel werken!

offtopic:
"imo mag je dat soort aannames lekker voor je houden :) heeft niemand wat aan namelijk."
was beetje pissig op moment van schrijven door omstandigheden, mijn excuses.
Pagina: 1