HTMLエンティティをデコードする組み込みの方法(例:"または')


11

最近、htmlエンティティのデコードの問題に遭遇しました。次の2つの文字列があります(名前付きと番号付きの2つのエンコード方法がどのように使用されているかに注意してください)。

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にこれを行う組み込みの方法がないとは信じません。私たちはいくつかのWebブラウザーを持っていますが、そのうちの少なくとも2つは組み込みであり、メールクライアントとフィードリーダーは言うまでもありません。

HTMLエンティティをデコードする組み込みの方法はありませんか?
最初の例の文字列を受け取り、2番目の例の文字列を返す関数を探しています。


何かがある場合は、DTDを解析でき、ドキュメント内のエンティティを検証できるので、nxmlコード内にある必要があると思います。
wasamasa 2014年

libxml-parse-html-regionもちろん、これを行いますが、HTMLタグも解析するため、必要以上に機能する可能性があります(そして、すべてのEmacsがLibXMLサポートで構築されているわけではないようです)。
Jon O.

回答:


7

Emacsにはに純粋なElisp XMLパーサーが含まれていますxml.el。そのxml-parse-string機能はその役割を果たしますが、ドキュメント化されていない内部関数のように見えます。文字列をXMLフラグメントとして処理することで適切に処理されないHTMLのみのエンティティがあるかどうかはわかりません。

このラッパー関数は、入力文字列から末尾のタグを単に省略しますが、より厳密にすることもできます。

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

LibXMLをサポートするEmacsでは、もう1つのちょっとハックな方法は、ラッパーを記述すること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編集を見ていませんでした。素晴らしいですね。
マラバルバ2014年

おかげで、私は答えを編集して、より簡単なxml.el解決策を最初にしました。
Jon O.

@Malabarba Jon O.と同じエンティティのデコードを実行するlisp/xml.el関数が常に含まれていることに注意してください。ただし、末尾のタグは省略されません。xml-substitute-specialdecode-entities
バジル

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.