2011-06-17 4 views
3

J'ai une page Web que j'ai chargé avec le chargement/balisage. J'ai besoin d'analyser un tas de choses, mais certaines des données sont dans les balises. Des idées de comment je peux l'analyser? Voici un échantillon de ce que j'ai (et essayé) jusqu'à présent:Comment analyser les balises HTML avec REBOL?

REBOL [] 

mess: { 
<td>Bob Sockaway</td> 
<td><a href=mailto:[email protected]>[email protected]</a></td> 
<td>9999</td> 
} 

rules: [ 
    some [ 
     ; The expression below /will/ work, but is useless because of specificity. 
     ; <td> <a href=mailto:[email protected]> s: string! </a> (print s/1) </td> | 

     ; The expression below will not work, because <a> doesn't match <a mailto=...> 
     ; <td> <a> s: string! </a> (print s/1) </td> | 

     <td> s: string! (print s/1) </td> | 

     tag! | string! ; Catch any leftovers. 
    ] 
] 

parse règles du mess charge/marge bénéficiaire

Ce produit:

Bob Sockaway 
9999 

je voudrais voir quelque chose de plus comme:

Bob Sockaway 
[email protected] 
9999 

Des pensées? Merci!

Remarque! Pour ce que ça vaut, je suis venu avec un bon ensemble de règles simples qui obtenir les résultats souhaités:

rules: [ 
    some [ 
     <td> any [tag!] s: string! (print s/1) any [tag!] </td> | 
     tag! | string! ; Catch any leftovers. 
    ] 
] 

Répondre

2

Lorsque mess est traité avec LOAD/MARKUP vous obtenez ceci (et je l'ai formaté + a commenté les types):

[ 
    ; string! 
    "^/" 

    ; tag! string! tag! 
    <td> "Bob Sockaway" </td> 

    ; string! 
    "^/" 

    ; tag! tag! 
    ;  string! 
    ; tag! tag! 
    <td> <a href=mailto:[email protected]> 
     "[email protected]" 
    </a> </td> 

    ; (Note: you didn't put the anchor's href in quotes above...) 

    ; string! 
    "^/" 

    ; tag! string! tag! 
    <td> "9999" </td> 

    ; string! 
    "^/" 
] 

Votre motif de sortie correspond à la série de la forme [<td> string! </td>] mais pas les choses de la forme [<td> tag! string! tag! </td>]. En écartant la question posée dans votre titre, vous pourriez résoudre ce dilemme particulier de plusieurs façons. On pourrait être de maintenir un compte si vous êtes à l'intérieur d'une balise TD et imprimer toutes les chaînes lorsque le nombre est non nul:

rules: [ 
    (td-count: 0) 
    some [ 
     ; if we see an open TD tag, increment a counter 
     <td> (++ td-count) 
     | 
     ; if we see a close TD tag, decrement a counter 
     </td> (-- td-count) 
     | 
     ; capture parse position in s if we find a string 
     ; and if counter is > 0 then print the first element at 
     ; the parse position (e.g. the string we just found) 
     s: string! (if td-count > 0 [print s/1]) 
     | 
     ; if we find any non-TD tags, match them so the 
     ; parser will continue along but don't run any code 
     tag! 
    ] 
] 

Cela produit la sortie que vous avez demandé:

Bob Sockaway 
[email protected] 
9999 

Mais vous vouliez également savoir, en substance, si vous pouviez effectuer une transition vers l'analyse de chaînes à partir de l'analyse de blocs dans le même ensemble de règles (sans passer directement au code ouvert). Je l'ai regardé "analyse mixte" semble être une fonctionnalité abordée dans Rebol 3. Pourtant, je ne pouvais pas le faire fonctionner en pratique. J'ai donc posé une question à moi.

How to mix together string parsing and block parsing in the same rule?

+0

Je vais devoir partager ce sur deux commentaires, parce que SO me déteste ... Merci votre réponse détaillée! Ce n'est pas exactement ce que je recherchais (ma faute!), mais cela résout le problème comme indiqué. J'espérais trouver comment analyser une étiquette! donc je pourrais obtenir des informations utiles à partir des différents arguments possibles à l'étiquette. Autrement dit, si l'étiquette! est '' ce serait bien d'être capable d'analyser le contenu de la chaîne href, au lieu de ce qui se trouve entre la balise "a". – oofoe

+0

Initialiser le compte-td à l'intérieur des règles est une bonne astuce et je n'avais pas pensé à maintenir l'état de l'analyse comme vous l'avez décrit. Cependant, voici une formulation plus élégante qui ne nécessite pas la variable supplémentaire: 'rules: [certains [ any [tag!] S: string! (print s/1) any [étiquette!] | marque! | chaîne! ]] ' Désolé pour le formatage de la merde. Apparemment, les commentaires ne sont pas des citoyens de première classe ...; -) – oofoe

+1

Votre règle d'analyse fonctionnera et aura une certaine sémantique sur les tables imbriquées, dépend de ce que vous voulez arriver dans ces cas. En tout cas, j'ai mis un lien vers une question que j'ai demandé d'essayer et de suivre sur le sujet que vous avez soulevé dans le titre ... – HostileFork

1

Je pense avoir trouvé une solution assez bonne. Il se peut que vous deviez généraliser si vous aviez beaucoup de tags différents dont vous avez besoin des attributs.

que je cherchais l'attribut id de la balise de requête !:

<query id="5"> 

Dans la règle d'analyse syntaxique pour la balise !, je l'ai fait:

| set t tag! (
    p: make block! t 
    if p/1 = 'query [_qid: to-integer p/3] 
) 

Plus de tags à regarder, je 'd cas d'utilisation. Et peut-être ce serait mieux de mettre _qid

to-integer select p 'id= 

J'ai fini par avoir besoin d'analyser une autre balise, ce qui est un beau modèle général

switch p/1 [ 
    field [_fid: to-integer p/id= _field_type: p/field_type=] 
    query [_qid: to-integer p/id=] 
] 
+0

qui ne fonctionne pas comme règle générale, vous devriez éviter les balises bizarres telles comme commentaires – pep

+0

Cela a vraiment très bien fonctionné. Désolé d'être en désaccord. – grantwparks

+0

preuve de principe: \t aa: load/markup { } parse aa [une partie [set t tag! (p: make block! t commute p/1 [! - [print select p '=]]) | chaîne!] ] – pep

Questions connexes