Cách tích hợp để giải mã các thực thể HTML (nghĩa là & quot; hoặc & # 39;)


11

Gần đây tôi gặp vấn đề về giải mã các thực thể html. Tôi có hai chuỗi sau ( Lưu ý cách sử dụng hai phương thức mã hóa, đặt tên và đánh số ).

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

Và tôi cần chuyển đổi chúng thành

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

Tìm kiếm xung quanh, tôi tìm thấy câu hỏi cũ này trên SO (đó là những gì tôi đang làm hiện tại), nhưng tôi từ chối tin rằng Emacs không có cách làm tích hợp này. Chúng tôi có một số trình duyệt web, ít nhất hai trong số đó tôi biết là tích hợp sẵn, chưa kể đến ứng dụng thư khách và trình đọc nguồn cấp dữ liệu.

Có cách nào để giải mã các thực thể html tích hợp không?
Tôi đang tìm một hàm lấy một chuỗi từ ví dụ đầu tiên và trả về một chuỗi từ ví dụ thứ hai.


Nếu có bất cứ điều gì, tôi cá là nó phải nằm trong mã nxml vì nó có thể phân tích các DTD và có thể xác thực các thực thể trong tài liệu.
wasamasa

libxml-parse-html-regionđiều này, tất nhiên, nhưng nó có thể làm được nhiều hơn bạn muốn, theo đó nó cũng phân tích cú pháp các thẻ HTML cũng như (Và không phải tất cả các Emac đều được xây dựng với sự hỗ trợ LibXML, tôi đoán vậy).
Jon O.

Câu trả lời:


7

Emacs bao gồm một trình phân tích cú pháp XML thuần túy xml.el, có xml-parse-stringchức năng thực hiện công việc, mặc dù nó có vẻ hơi giống một hàm nội bộ không có giấy tờ. Tôi không chắc chắn liệu có bất kỳ thực thể nào chỉ có HTML sẽ không được xử lý đúng cách hay không bằng cách coi chuỗi là một đoạn XML.

Hàm bao bọc này đơn giản sẽ bỏ qua bất kỳ thẻ theo dõi nào từ chuỗi đầu vào, mặc dù bạn có thể làm cho nó chặt chẽ hơn:

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

Trong Emacs với sự hỗ trợ của LibXML, một cách hơi khó hiểu khác là viết một trình bao bọc xung quanh libxml-html-parse-region. Do trình phân tích cú pháp LibXML giả định đối số của nó là một tài liệu HTML hoàn chỉnh, nên hàm bao bọc phải trích xuất dữ liệu ký tự được phân tích cú pháp từ cấu trúc tài liệu được trả về, sử dụng pcase. Cố gắng giải mã một chuỗi chứa bất kỳ thẻ HTML nào sẽ gây ra lỗi:

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

Các kết quả:

(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

Có vẻ hơi lạc hậu khi giải mã một đoạn tài liệu bằng cách phân tích nó như một tài liệu hoàn chỉnh, chỉ để loại bỏ ngay các thẻ xung quanh. Mặt khác, sử dụng LibXML phải nhanh và cho kết quả chính xác.


Xin lỗi, tôi đã không thấy chỉnh sửa xml của bạn. Trông tuyệt.
Malabarba

Cảm ơn - Tôi đã chỉnh sửa câu trả lời để đặt xml.elgiải pháp đơn giản hơn trước.
Jon O.

@Malabarba Lưu ý rằng lisp/xml.elluôn có chức năng xml-substitute-specialthực hiện giải mã thực thể giống như của Jon O.'sdecode-entities . Nó không, tuy nhiên, bỏ qua các thẻ theo dõi.
Basil

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.