Modalità integrata di decodifica di entità HTML (ad es. & Quot; o & # 39;)


11

Di recente ho riscontrato il problema della decodifica di entità html. Ho le seguenti due stringhe ( nota come vengono utilizzati, denominati e numerati due metodi di codifica ).

The old "how to fold xml" question
Babel doesn't wrap results in verbatim

E ho bisogno di convertirli in

The old "how to fold xml" question
Babel doesn't wrap results in verbatim

Cercando in giro, ho trovato questa vecchia domanda su SO (che è quello che sto facendo per il momento), ma mi rifiuto di credere che Emacs non abbia un modo integrato per farlo. Abbiamo diversi browser Web, almeno due dei quali sono integrati, per non parlare dei client di posta e dei lettori di feed.

Non esiste un modo integrato per decodificare le entità html?
Sto cercando una funzione che prende una stringa dal primo esempio e restituisce una stringa dal secondo esempio.


Se c'è qualcosa, scommetto che deve essere nel codice nxml poiché è in grado di analizzare i DTD e può convalidare le entità nel documento.
Wasamasa,

libxml-parse-html-regionfa questo, ovviamente, ma potrebbe fare più di quello che vuoi, in quanto analizza anche i tag HTML ... (E non tutti gli Emacs sono costruiti con il supporto di LibXML, immagino).
Jon O.,

Risposte:


7

Emacs include un parser XML pure-Elisp in xml.el, la cui xml-parse-stringfunzione svolge il compito, sebbene sembri un po 'una funzione interna non documentata. Non sono sicuro se ci sono entità solo HTML che non verranno gestite correttamente trattando la stringa come un frammento XML.

Questa funzione wrapper ometterà semplicemente qualsiasi tag finale dalla stringa di input, anche se potresti renderlo più rigoroso:

(defun decode-entities (html)
  (with-temp-buffer
    (save-excursion (insert html))
    (xml-parse-string)))

(decode-entities "The old "how to fold xml" question")
;; => "The old \"how to fold xml\" question"

(decode-entities "doesn't")
;; => "doesn't"

(decode-entities "string with trailing tag: <tag/>")
;; => "string with trailing tag: "

In Emacs con supporto LibXML, un altro modo un po 'hacker sarebbe scrivere un wrapper libxml-html-parse-region. Poiché il parser LibXML assume che il suo argomento sia un documento HTML completo, la funzione wrapper deve estrarre i dati dei caratteri analizzati dalla struttura del documento restituito, usando pcase. Tentare di decodificare una stringa che contiene tag HTML genererà un errore:

(defun decode-entities/libxml (html)
  (with-temp-buffer
    (insert html)
    (let ((document
           (libxml-parse-html-region (point-min) (point-max))))
      (pcase document
        (`(html nil
                (body nil
                      (p nil
                         ,(and (pred stringp)
                               content))))
          content)
        (_ (error "Unexpected parse result: %S" document))))))

risultati:

(decode-entities/libxml "The old &quot;how to fold xml&quot; question")
     ; => "The old \"how to fold xml\" question"
(decode-entities/libxml "doesn&#39;t") ; => "doesn't"

(decode-entities/libxml "<html>")              ; produces an error

Sembra un po 'arretrato decodificare un frammento di documento analizzandolo come un documento completo, solo per rimuovere immediatamente i tag circostanti. D'altra parte, l'uso di LibXML dovrebbe essere veloce e dare risultati accurati.


Spiacenti, non avevo visto la tua modifica XML. Sembra stupendo.
Malabarba,

Grazie: ho modificato la risposta per mettere al xml.elprimo posto la soluzione più semplice .
Jon O.

@Malabarba noti che lisp/xml.elha sempre inclusa la funzione xml-substitute-special, che svolge la stessa entità decodifica come Jon O. didecode-entities . Tuttavia, non omette i tag finali.
Basilio,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.