Creak : Une bibliothèque d'analyse HTML pour Swift | Original, traduit par l'IA
Creak est conçu pour analyser efficacement les documents HTML et construire une structure arborescente représentant les éléments du document. Le processus d’analyse implique plusieurs étapes et composants clés qui travaillent ensemble pour atteindre cet objectif. Voici une explication détaillée de la manière dont Creak analyse le HTML :
Aperçu du processus d’analyse
- Initialisation : Chargement et nettoyage de la chaîne HTML.
- Tokenisation : Décomposition de la chaîne HTML en tokens représentant les différentes parties du HTML, telles que les balises et le texte.
- Construction de l’arbre : Utilisation des tokens pour construire une structure arborescente représentant les éléments et le texte du document HTML.
Composants clés
- Classe Dom : Gère l’ensemble du processus d’analyse et stocke le nœud racine de l’arbre HTML analysé.
- Classe Content : Fournit des fonctions utilitaires pour la tokenisation des chaînes HTML.
- Classes HtmlNode et TextNode : Représentent les éléments et les nœuds de texte dans un document HTML.
- Classe Tag : Représente les balises HTML et leurs attributs.
Étapes détaillées d’analyse
1. Initialisation
La classe Dom est responsable de l’initialisation du processus d’analyse. La méthode loadStr prend une chaîne HTML brute, la nettoie et initialise l’objet Content.
public func loadStr(str: String) -> Dom {
raw = str
let html = clean(str)
content = Content(content: html)
parse()
return self
}
2. Tokenisation
La classe Content fournit des fonctions utilitaires pour la tokenisation de chaînes HTML. Elle inclut des méthodes pour copier des caractères à partir de la position actuelle, sauter des caractères, ainsi que pour traiter des tokens tels que les balises et les attributs.
- copyUntil : Copie les caractères à partir de la position actuelle jusqu’à ce qu’un caractère spécifié soit rencontré.
- skipByToken : Saute les caractères en fonction du jeton spécifié.
Ces méthodes sont utilisées pour identifier et extraire différentes parties du HTML, telles que les balises, les attributs et le contenu textuel.
3. Construction de la structure en arbre
La méthode parse de la classe Dom parcourt la chaîne HTML, identifie les balises et le texte, et construit une structure arborescente composée de HtmlNode et TextNode.
private func parse() {
root = HtmlNode(tag: "root")
var activeNode: InnerNode? = root
while activeNode != nil {
let str = content.copyUntil("<")
if (str == "") {
let info = parseTag()
if !info.status {
activeNode = nil
continue
}
if info.closing {
let originalNode = activeNode
while activeNode?.tag.name != info.tag {
activeNode = activeNode?.parent
if activeNode == nil {
activeNode = originalNode
break
}
}
if activeNode != nil {
activeNode = activeNode?.parent
}
continue
}
if info.node == nil {
continue
}
let node = info.node!
activeNode!.addChild(node)
if !node.tag.selfClosing {
activeNode = node
}
} else if (trim(str) != "") {
let textNode = TextNode(text: str)
activeNode?.addChild(textNode)
}
}
}
- Nœud racine : L’analyse commence à partir du nœud racine (
HtmlNode, avec la balise “root”). - Nœud actif : La variable
activeNodesuit le nœud en cours de traitement. - Contenu textuel : Si du contenu textuel est détecté, un
TextNodeest créé et ajouté au nœud actuel. - Analyse des balises : Si une balise est détectée, la méthode
parseTagest appelée pour la traiter.
Analyse des étiquettes
La méthode parseTag gère l’identification et le traitement des balises.
private func parseTag() -> ParseInfo {
var result = ParseInfo()
if content.char() != ("<" as Character) {
return result
}
if content.fastForward(1).char() == "/" {
var tag = content.fastForward(1).copyByToken(Content.Token.Slash, char: true)
content.copyUntil(">")
content.fastForward(1)
tag = tag.lowercaseString
if selfClosing.contains(tag) {
result.status = true
return result
} else {
result.status = true
result.closing = true
result.tag = tag
return result
}
}
let tag = content.copyByToken(Content.Token.Slash, char: true).lowercaseString
let node = HtmlNode(tag: tag)
while content.char() != ">" &&
content.char() != "/" {
let space = content.skipByToken(Content.Token.Blank, copy: true)
if space?.characters.count == 0 {
content.fastForward(1)
continue
}
let name = content.copyByToken(Content.Token.Equal, char: true)
if name == "/" {
break
}
if name == "" {
content.fastForward(1)
continue
}
content.skipByToken(Content.Token.Blank)
if content.char() == "=" {
content.fastForward(1).skipByToken(Content.Token.Blank)
var attr = AttrValue()
let quote: Character? = content.char()
if quote != nil {
if quote == "\"" {
attr.doubleQuote = true
} else {
attr.doubleQuote = false
}
content.fastForward(1)
var string = content.copyUntil(String(quote!), char: true, escape: true)
var moreString = ""
repeat {
moreString = content.copyUntilUnless(String(quote!), unless: "=>")
string += moreString
} while moreString != ""
attr.value = string
content.fastForward(1)
node.setAttribute(name, attrValue: attr)
} else {
attr.doubleQuote = true
attr.value = content.copyByToken(Content.Token.Attr, char: true)
node.setAttribute(name, attrValue: attr)
}
} else {
node.tag.setAttribute(name, attrValue: AttrValue(nil, doubleQuote: true))
if content.char() != ">" {
content.rewind(1)
}
}
}
content.skipByToken(Content.Token.Blank)
if content.char() == "/" {
node.tag.selfClosing = true
content.fastForward(1)
} else if selfClosing.contains(tag) {
node.tag.selfClosing = true
}
content.fastForward(1)
result.status = true
result.node = node
return result
}
- Reconnaissance des balises : Cette méthode identifie si une balise est une balise ouvrante ou fermante.
- Attributs : Les attributs de la balise sont analysés et ajoutés au
HtmlNode. - Balises auto-fermantes : Les balises auto-fermantes sont gérées de manière appropriée.
Conclusion
Le processus d’analyse de Creak implique l’initialisation du contenu HTML, sa tokenisation et la construction d’une structure arborescente de nœuds. La classe Dom gère l’analyse globale, tandis que la classe Content fournit des fonctions utilitaires pour la tokenisation des chaînes HTML. Les classes HtmlNode et TextNode représentent respectivement les éléments et le texte dans un document HTML, et la classe Tag gère les attributs des balises. Cette approche efficace et organisée fait de Creak un outil puissant pour l’analyse HTML en Swift.