Вбудований спосіб декодування об’єктів HTML (тобто & quot; або & # 39;)


11

Нещодавно я зіткнувся з проблемою декодування html-об'єктів. У мене є наступні два рядки ( зверніть увагу на те, як використовуються два способи кодування, названі та пронумеровані ).

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

І мені потрібно їх перетворити

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

Шукаючи навколо, я знайшов це старе питання щодо SO (що я зараз і роблю), але я відмовляюся вірити, що Emacs не має вбудованого способу цього зробити. У нас є кілька веб-браузерів, принаймні два з яких я знаю вбудовані, не кажучи вже про поштових клієнтів та читачів каналів.

Чи не існує вбудованого способу розшифровки html-об'єктів?
Я шукаю функцію, яка бере рядок з першого прикладу і повертає рядок з другого прикладу.


Якщо є щось, я думаю, що він повинен бути в коді nxml, оскільки він може розбирати DTD і може перевіряти сутності в документі.
wasamasa

libxml-parse-html-regionце, звичайно, це робить, але це може зробити більше, ніж ви хочете, розбираючи HTML-теги також… (І не всі Emacs створені з підтримкою LibXML, я думаю).
Джон О.

Відповіді:


7

Emacs включає чистий аналізатор Elisp XML в xml.el, xml-parse-stringфункція якого виконує цю роботу, хоча це схоже на недокументовану внутрішню функцію. Я не впевнений, чи є якісь лише HTML-елементи, з якими не буде належним чином оброблятися, обробляючи рядок як фрагмент XML.

Ця функція обгортки просто опустить будь-які проміжні теги з вхідного рядка, хоча ви можете зробити це суворішим:

(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: "

У Emacs із підтримкою LibXML ще одним злегка шахрайським способом було б написання обгортки навколо libxml-html-parse-region. Оскільки аналізатор LibXML припускає, що його аргумент є повноцінним HTML-документом, функція обгортки повинна витягувати дані про розбір символів із поверненої структури документа, використовуючи pcase. Спроба розшифрувати рядок, що містить будь-які теги HTML, призведе до помилки:

(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))))))

Результати:

(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

Декорувати фрагмент документа, здається, трохи назад, аналізуючи його як повний документ, лише негайно знімати з оточуючих тегів. З іншого боку, використання LibXML повинно бути швидким і давати точні результати.


Вибачте, я не бачив вашого редагування XML. Виглядає дивовижно.
Малабарба

Дякую - я відредагував відповідь, щоб xml.elпершим поставити простіше рішення.
Джон О.

@Malabarba Зверніть увагу , що lisp/xml.elзавжди включали в себе функцію xml-substitute-special, яка виконує ту ж сутність декодування , як Джон О. - хdecode-entities . Однак він не опускає проміжні теги.
Василь

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.