Arbre du DOM

L'arbre du DOM (pour Document Object Model ) est une façon de représenter les documents HTML sous forme d'arbres dont les nœuds sont les balises et les contenus textuels du document. On se limite dans cet exercice aux nœuds correspondant à des balises HTML.

Considérons par exemple le document HTML ci-dessous (on n'a noté que les balises et pas leur contenu textuel) :

Document HTML
<html>     
    <head>   
    </head>   
    <body>   
        <h1>   
          <div>
          </div>
          <p>
          </p>
      </h1>   
      <div>
          <p>  
          </p>  
      </div>
  </body>   
</html>     

On rappelle que la plupart des balises HTML fonctionnent par paires : une balise ouvrante (par exemple <p>) et une balise fermante (dans ce cas </p>).

Ce document HTML correspond à l'arbre ci-dessous :

Arbre DOM

On représente les arbres de cet exercices à l'aide de la programmation orientée objet. On introduit donc une classe Arbre caractérisée par deux attributs :

  • le nom le la balise à la racine de l'arbre (attribut nom, au format str) ;
  • la liste des sous-arbres de cet arbre (attribut enfants qui est une liste, potentiellement vide, d'éléments de type Arbre).
Exemple d'utilisation
>>> p = Arbre("p", [])  # un arbre représentant une balise 'p', sans enfants
>>> img = Arbre("img", [])
>>> div = Arbre("div", [p, img])
>>> div.nom
'div'
>>> print(div)
div  
  p  
  img
>>> for enfant in div.enfants:
...     print(enfant.nom)
...
p
img
La classe Arbre
class Arbre:
    def __init__(self, nom, enfants):
        self.nom = nom
        self.enfants = enfants

    def __repr__(self, decalage=0):
        s = f"{' ' * decalage}{self.nom}\n"
        for enfant in self.enfants:
            s += enfant.__repr__(decalage + 2)
        return s

Si a est un objet de type Arbre, on peut donc :

  • récupérer le nom de la balise en faisant a.nom ;
  • parcourir ses enfants en faisant for e in a.enfants: ....

L'arbre du DOM utilisé dans les exemples est créé par le script ci-dessous :

Arbre utilisé dans les exercices
p1 = Arbre("p", [])
div1 = Arbre("div", [p1])
p2 = Arbre("p", [])
div2 = Arbre("div", [])
h1 = Arbre("h1", [div2, p2])
body = Arbre("body", [h1, div1])
head = Arbre("head", [])
arbre_dom = Arbre("html", [head, body])
1. Nombre total de balises dans l'arbre

Écrire la fonction nb_balises qui prend en paramètre un objet de type Arbre représentant un arbre du DOM et renvoie le nombre total de balises qu'il contient.

Exemples

Arbre DOM

>>> nb_balises(body)
6
>>> nb_balises(arbre_dom)
8

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013ben4vi3mo5_tPhklpwf(: cg.a=rySu/)2s1+d050M0c0m0A0g0q0J0w0x0q0A0J0J0B010m0g0r010406050J0F0i0i0A0C0D040E0j0q0F0%0j0d050G0.0:0=0@0,0r040517101a0G170,0M0g0f0V0X0Z0#0o0g0y0o0q1o0o0m0*050Q0b0q0c1j0Y0!011n1p1r1p0m1x1z1v0m0C180m0o0V0`0J0r0A0d0#0I011B1l010t0S0c0d0A0i0c1v1U1W1#1D1(1z1+1-0*0a0w0n0C0j0r0j0J0g0}0d0w0O1S0C0C0c0x25101:0d180G1Q2i1N1P1O1w0M1=0#1r0d1*221v1g1i0W1C2s0g2u0d0j2y1v0r2b182g2i2M0-1V262A1$2F0C0;0q0*0K2f2Q0+2P1;2S1D2U2W0*0I2!1W2$2g2r012+0A2X040h2/2h0,2=2)0#2^2`0e2}2;2Q2?330*0k361b2K102y2l0M1P2q31010x2G1.183h193f2O112#053o0O2L383m0p0*0O0t3d301k1D0s0*0w3I3C3K320t0*0d0b0l0b2_0g0J0c0J3P2(3R010)040u3(2R3*0d0*0=0b2b3/2?3,0H0v36060w413O3J2B2@0*0m36433Q450j0*0B492%3:450i0g2Y3 424a3)453E040t0j0C4g442T0*1*0t1W483w2:4p4i1$0j3M042D4x4b4z043@3_4F2h4h2?4d040z3`3m3=044B4D3%4U3B4q1$3,3~4,404o424W4$474O4.1D4Y0L4f4,4H393U3W3Y1r3#4+2O4y1D3,3.4,4_3;4A0d4C0d4E5b4P5d0*0H4n4^5c0#4s2b0m0F0C0 525h454%5n2#0,0G3z0c2i2J5M3g1h3i2l2o2j0A1y5P0G3h5J0O0Q0S0J04.
2. Nombre de balises d'un certain type

Écrire la fonction compte_balises qui prend en paramètres un objet de type Arbre représentant un arbre du DOM ainsi qu'une chaîne de caractères balise et renvoie le nombre de balises de ce type présentes dans l'arbre.

Exemples

Arbre DOM

>>> compte_balises(arbre_dom, "p")
2
>>> compte_balises(arbre_dom, "div")
2
>>> compte_balises(arbre_dom, "img")
0

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013ben,4vi3mo5_tPhklpwf(: cg.a=ry0S6u/72)s1+d050Q0c0n0B0h0r0N0x0y0r0B0N0N0C010n0h0s010406050N0I0j0j0B0D0E040G0k0r0I0+0k0d050J0=0@0_0{0:0s04051b141e0J1b0:0Q0h0g0Z0#0%0)0p0h0z0p0r1s0p0n0.050U0b0r0c1n0$0(011r1t1v1t0n1B1D1z0n0D1c0n0p0Z0~0N0s0B0d0)0L011F1p010u0W0c0d0B0j0c1z1Y1!1)1H1,1D1/1;0.0a0x0o0D0k0s0k0N0h110d0x0S1W0D0D0c0y29141@0d1c0J1U2m1R1T1S1A0Q1_0)1v0d1.261z1k1m0!1G2w0h2y0d0k2C1z0s2f1c2k2m2Q0;1Z2a2E1*2J0D0^0r0.0O2j2U0/2T1^2W1H2Y2!0.0L2(1!2*2k2v012/0B2#040i2?2l0:2_2-0)2|2~0f312^2U2`370.0l3a333c352{0k2Z2}0.0H3h2+2V1o2.3m2:040K3a1f2O142C2p0Q1T2u3k0y2K1=1c3E1d3C2S152)053K0S2P3j3u0)0q0.0S0u3A343Z010t0.0x3)3Y2F2{0u0.3K0j0s0n0c0m0b2}0h0N0c0N3:2,3+0-040v453t3=0d0.0_0b2f4b2`480e3a3/3*4d0.3 1v424j3k480M0w3h0x4B4o3;2X0.0n4n3s2`0k0.0C4I4p1*0j0h0.0F4A4C4J3k3#040h3(3S2@4D464q044g4i4%2l4X3+4L040A4v3+4e042J0j4O4E1H4?0C4N4/044)4c4F044s410c4_3=484z55064C5k573d4G4 4*1*525p581H4R2$4V4B4;3=4Z0u3m5t5n041.0u1!4H555m3k0k3-4!135M5A594-5d555U510.4^5Y4P2.0.5I5K445%500)5g5y5l5Z365o5T5(0)4?0P542Q5N4`3^0k3`3|3~40425-2S5{01484a5.5q5)5H0d5J0d5L6b5/6d0.4m5`6p4{5b4u6g5u5:0.0M5=5@014Z2f0n0I0D5S606E4{6n2)0:0J3V0c2m2N6U3D1l3F2p2s2n0B1C6X0J3E6R0S0U0W0N04.
3. Nombre de balises en cascade

Le style d'un élément de l'arbre DOM peut être défini à l'aide de règles CSS (pour Cascading Style Sheet).

Une règle CSS s'applique à certains éléments de l'arbre et à tous leurs descendants (elle s'applique en cascade).

Par exemple, si une règle vise les éléments de type div, elle s'appliquera à toutes les div mais aussi à tous les éléments contenus dans les sous-arbres de racine un élément div quels que soient leur type.

Arbre DOM

Écrire la fonction compte_balises_cascade qui prend en paramètres un objet de type Arbre représentant un arbre du DOM ainsi qu'une chaîne de caractères balises et renvoie le nombre de balises auxquelles s'appliquent une règle CSS visant ce type de balise.

Une version corrigée des fonctions nb_balises et compte_balises est directement utilisable dans l'éditeur ci-dessous.

Exemples

Arbre DOM

>>> compte_balises_cascade(arbre_dom, "p")
2
>>> compte_balises_cascade(arbre_dom, "div")
3
>>> compte_balises_cascade(arbre_dom, "img")
0

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013ben,4vi+3mo5_tPhklpwf(: cg.a=ry0S6u/72)s18d050R0c0o0C0h0s0O0y0z0s0C0O0O0D010o0h0t010406050O0J0k0k0C0E0F040H0l0s0J0,0l0d050K0?0^0`0|0;0t04051c151f0K1c0;0R0h0g0!0$0(0*0q0h0A0q0s1t0q0o0/050V0b0s0c1o0%0)011s1u1w1u0o1C1E1A0o0E1d0o0q0!0 0O0t0C0d0*0M011G1q010v0X0c0d0C0k0c1A1Z1#1*1I1-1E1:1=0/0a0y0p0E0l0t0l0O0h120d0y0T1X0E0E0c0z2a151^0d1d0K1V2n1S1U1T1B0R1`0*1w0d1/271A1l1n0#1H2x0h2z0d0l2D1A0t2g1d2l2n2R0=1!2b2F1+2K0E0_0s0/0P2k2V0:2U1_2X1I2Z2#0/0M2)1#2+2l2w012:0C2$040j2@2m0;2`2.0*2}2 0f322_2V2{380/0m3b343d362|0l2!2~0/0I3i2,2W1p2/3n2;040L3s353v373x3p040Q3b1g2P152D2q0R1U2v3l0z2L1?1d3N1e3L2T162*053T0T2Q3k3D010r0/0T0v3J3C2G010u0/0y3=3+3@0d0v0/3T0k0t0o0c0n0b2~0h0O0c0O0n0z0%4f0T3|2-3,0.040w4j3u3~0/0`0b2g4p2{4m0e3b3{3?2Y0/481w4b4w3l4m0N0x3i0y4O4B3}1+3.040h3;3#2^4Q4k4r044t4v4X2m3t2{0l0/0B4I3,0d0/2K0k4A4+3l4-040D0D4_4C2/4E494H4)3*4!1+4m4M56064P5e4Z4q4S0/2g0o0J0E14565g3e4?0b47544c4:3@4m4o564`4;4s0E4u0c5x590/0N4N4P5C3@4T0c0Y5H5B510*5a5M5f5q3l4=040o504R1I4|4 5p5O1+0k0h0/0G5Y5f5/1I4T0v3n5)5852041/0v1#5(5.5V010l3_4U5o2R5!5D4$5F4(2T684|4/5U5*370/63650O5I1I5X5c5Z5Z5`6q5%5 5h5+0/0i5-6e6B2|410l43455u4G4c4e4g0C4i6o605W0/5A6k6p6M623 656v6!044z676(5$4F4a5T6%6Z014K5^5e6L4T5k5m6d2*6f4#662R0;0K3(0c2n2O7d3M1m3O2q2t2o0C1D7g0K3N7a0T0V0X0O04.