วิธีถอดรหัสเอนทิตี 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 เช่นกันฉันเดา)
Jon O.

คำตอบ:


7

Emacs รวมถึงตัวแยกวิเคราะห์ XML แบบบริสุทธิ์ - Elisp xml.elซึ่งxml-parse-stringฟังก์ชันทำหน้าที่แม้ว่ามันจะดูเหมือนฟังก์ชั่นภายในที่ไม่มีเอกสาร ฉันไม่แน่ใจว่ามีเอนทิตี HTML เท่านั้นหรือไม่ซึ่งจะไม่ได้รับการจัดการอย่างถูกต้องโดยถือว่าสตริงเป็นส่วน XML

ฟังก์ชั่น wrapper นี้จะละเว้นแท็กต่อท้ายใด ๆ จากสตริงป้อนข้อมูลถึงแม้ว่าคุณสามารถทำให้มันเข้มงวดขึ้น:

(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 อีกวิธี hackish 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 ของคุณ ดูน่ากลัว
Malabarba

ขอบคุณ - ฉันแก้ไขคำตอบเพื่อให้การxml.elแก้ปัญหาง่ายขึ้นเป็นอันดับแรก
Jon O.

หมายเหตุ @Malabarba ที่lisp/xml.elได้รวมเสมอฟังก์ชั่นxml-substitute-specialซึ่งดำเนินกิจการที่เดียวกันถอดรหัสเป็นจอนทุมของ decode-entitiesอย่างไรก็ตามจะไม่ละเว้นแท็กต่อท้าย
เพรา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.