3

数値 HTML/XML エンティティのエスケープを解除するための適切な実装は何
ですか?

単体テストとして表現:

local orig = "It's the "end" &ok;
"
local fixd = unescape(orig) -- Implement this
assert( fixd == "It's the \"end\" &ok;\n" )
4

3 に答える 3

9

以下は、中核となる名前付き XML エンティティも処理する単純な実装です。

function unescape(str)
  str = string.gsub( str, '&lt;', '<' )
  str = string.gsub( str, '&gt;', '>' )
  str = string.gsub( str, '&quot;', '"' )
  str = string.gsub( str, '&apos;', "'" )
  str = string.gsub( str, '&#(%d+);', function(n) return string.char(n) end )
  str = string.gsub( str, '&#x(%d+);', function(n) return string.char(tonumber(n,16)) end )
  str = string.gsub( str, '&amp;', '&' ) -- Be sure to do this after all others
  return str
end

print(unescape("&#34;Hello&quot; &apos;World&#39;")) --> "Hello" 'World'

ただし、これは 1 つの異常なケースで失敗することに注意してください: 数値のアンパサンド エンティティの後にテキストが続きますamp;:

print(unescape("Ampersand entity is &#38;amp;")) --> Ampersand entity is &
-- The result should actually be                     Ampersand entity is &amp;

すべてのエンティティを一度に処理することでこのエッジ ケースを修正できますが、コードはかなり醜くなります。

function unescape(str)
  local map={ ["lt"]="<", ["gt"]=">", ["amp"]="&", ["quot"]='"', ["apos"]="'" }
  str = string.gsub( str, '(&(#?x?)([%d%a]+);)', function(orig,n,s)
    return (n=='' and map[s])
           or (n=="#x" and tonumber(s,16)) and string.char(tonumber(s,16))
           or (n=="#" and tonumber(s)) and string.char(s)
           or orig
  end )
  return str
end

print(unescape("Ampersand entity is &#38;amp;")) --> Ampersand entity is &amp;

最後に、もう少し高速化するためにアンラップできます。

local gsub, char = string.gsub, string.char
local entityMap  = {["lt"]="<",["gt"]=">",["amp"]="&",["quot"]='"',["apos"]="'"}
local entitySwap = function(orig,n,s)
  return (n=='' and entityMap[s])
         or (n=="#" and tonumber(s)) and string.char(s)
         or (n=="#x" and tonumber(s,16)) and string.char(tonumber(s,16))
         or orig
end
function unescape(str)
  return (gsub( str, '(&(#?x?)([%d%a]+);)', entitySwap ))
end
于 2013-02-15T17:06:45.567 に答える
0

LuaRocks経由で htmlEntities-for-luaモジュールが利用できるようになりました。代わりにそれを使用する必要があります。コード内で string.gsub の反復を 3 回しか使用しないため、より高速完全です。

htmlEntities = require('htmlEntities')

print(htmlEntities.decode(yourString))

または、現在の機能のドロップイン代替として使用します。

myUnescape = require('htmlEntities').decode
于 2019-03-11T22:26:44.970 に答える