Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
取消跳过HTML实体(包括命名实体)_Html_String_Haskell - Fatal编程技术网

取消跳过HTML实体(包括命名实体)

取消跳过HTML实体(包括命名实体),html,string,haskell,Html,String,Haskell,这个问题类似于前面关于堆栈溢出的问题但是,公认的答案并没有解决命名HTML实体的问题,例如ä用于字符ä因此它无法取消所有HTML的扫描 我有一些传统的HTML,它使用命名的HTML实体来表示非ASCII字符。也就是说,ö而不是ö,ä而不是ä等等。可以在维基百科上找到 我想以一种快速有效的方式将这些HTML实体转换成它们的字符等价物 我在Python 3中使用正则表达式编写了这样的代码: import re import html.entities s = re.sub

这个问题类似于前面关于堆栈溢出的问题但是,公认的答案并没有解决命名HTML实体的问题,例如
ä用于字符
ä
因此它无法取消所有HTML的扫描

我有一些传统的HTML,它使用命名的HTML实体来表示非ASCII字符。也就是说,
ö
而不是
ö
ä
而不是
ä
等等。可以在维基百科上找到

我想以一种快速有效的方式将这些HTML实体转换成它们的字符等价物


我在Python 3中使用正则表达式编写了这样的代码:

import re
import html.entities

s = re.sub(r'&(\w+?);', lambda m: chr(html.entities.name2codepoint[m.group(1)]), s)
然而,正则表达式在Haskell中似乎不是很流行、很快或很容易使用


Text.HTML.TagSoup.Entity
(TagSoup)有一个有用的表和函数,用于映射命名实体tpo代码点。使用这个和regex tdfa包,我在Haskell中创造了一个非常慢的等价物:

{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString.Lazy.Char8 as L
import Data.ByteString.Lazy.UTF8 as UTF8
import Text.HTML.TagSoup.Entity (lookupEntity)
import Text.Regex.TDFA ((=~~))

unescapeEntites :: L.ByteString -> L.ByteString
unescapeEntites = regexReplaceBy "&#?[[:alnum:]]+;" $ lookupMatch
 where
  lookupMatch m =
    case lookupEntity (L.unpack . L.tail . L.init $ m) of
      Nothing -> m
      Just x -> UTF8.fromString [x]

-- regex replace taken from http://mutelight.org/articles/generating-a-permalink-slug-in-haskell
regexReplaceBy :: L.ByteString -> (L.ByteString -> L.ByteString) -> L.ByteString -> L.ByteString
regexReplaceBy regex f text = go text []
 where
  go str res =
    if L.null str
      then L.concat . reverse $ res
      else
        case (str =~~ regex) :: Maybe (L.ByteString, L.ByteString, L.ByteString) of
          Nothing -> L.concat . reverse $ (str : res)
          Just (bef, match , aft) -> go aft (f match : bef : res)
unescapeEntities
函数的运行速度比上面的Python版本慢几个数量级。Python代码可以在7秒内转换大约130MB,而我的Haskell版本可以运行几分钟


我正在寻找一个更好的解决方案,主要是在速度方面。但是,如果可能的话,我也希望避免使用正则表达式(速度和避免正则表达式似乎在Haskell中是齐头并进的)。

您可以安装web编码包,获取decodeHtml函数的源代码并添加所需的字符(对我来说很有用)。这就是您所需要的:

import Data.Maybe
import qualified Web.Encodings.StringLike as SL
import Web.Encodings.StringLike (StringLike)
import Data.Char (ord)

-- | Decode HTML-encoded content into plain content.
--
-- Note: this does not support all HTML entities available. It also swallows
-- all failures.
decodeHtml :: StringLike s => s -> s
decodeHtml s = case SL.uncons s of
    Nothing -> SL.empty
    Just ('&', xs) -> fromMaybe ('&' `SL.cons` decodeHtml xs) $ do
        (before, after) <- SL.breakCharMaybe ';' xs
        c <- case SL.unpack before of -- this are small enough that unpack is ok
            "lt" -> return '<'
            "gt" -> return '>'
            "amp" -> return '&'
            "quot" -> return '"'
            '#' : 'x' : hex -> readHexChar hex
            '#' : 'X' : hex -> readHexChar hex
            '#' : dec -> readDecChar dec
            _ -> Nothing -- just to shut up a warning
        return $ c `SL.cons` decodeHtml after
    Just (x, xs) -> x `SL.cons` decodeHtml xs

readHexChar :: String -> Maybe Char
readHexChar s = helper 0 s where
    helper i "" = return $ toEnum i
    helper i (c:cs) = do
        c' <- hexVal c
        helper (i * 16 + c') cs

hexVal :: Char -> Maybe Int
hexVal c
    | '0' <= c && c <= '9' = Just $ ord c - ord '0'
    | 'A' <= c && c <= 'F' = Just $ ord c - ord 'A' + 10
    | 'a' <= c && c <= 'f' = Just $ ord c - ord 'a' + 10
    | otherwise = Nothing

readDecChar :: String -> Maybe Char
readDecChar s = do
    case reads s of
        (i, _):_ -> Just $ toEnum (i :: Int)
        _ -> Nothing
导入数据。可能吧
将符合条件的Web.Encodings.StringLike导入为SL
导入Web.Encodings.StringLike(StringLike)
导入数据字符(ord)
--|将HTML编码的内容解码为普通内容。
--
--注意:这并不支持所有可用的HTML实体。它也能吞咽
--所有的失败。
解码HTML::StringLike s=>s->s
解码HTML s=案例SL.UNCON s of
无->SL.empty
Just('&',xs)->fromMaybe('&'`SL.cons`decode html xs)$do
(之前、之后)返回'>'
“amp”->返回“&”
“quot“->返回”
“#”:“x”:十六进制->读取十六进制字符十六进制
“#”:“X”:十六进制->读取十六进制字符十六进制
“#”:dec->readDecChar dec
_->没什么--只是为了停止警告
之后返回$c`SL.cons`decodeHtml
只需(x,xs)->x`SL.cons`decodeHTMLxs
readHexChar::String->Maybe Char
readHexChar s=helper 0 s其中
helper i”“=返回$toEnum i
助手i(c:cs)=do

c'您可以安装web编码软件包,获取decodeHtml函数的源代码并添加所需的字符(适用于我)。这就是您所需的全部:

import Data.Maybe
import qualified Web.Encodings.StringLike as SL
import Web.Encodings.StringLike (StringLike)
import Data.Char (ord)

-- | Decode HTML-encoded content into plain content.
--
-- Note: this does not support all HTML entities available. It also swallows
-- all failures.
decodeHtml :: StringLike s => s -> s
decodeHtml s = case SL.uncons s of
    Nothing -> SL.empty
    Just ('&', xs) -> fromMaybe ('&' `SL.cons` decodeHtml xs) $ do
        (before, after) <- SL.breakCharMaybe ';' xs
        c <- case SL.unpack before of -- this are small enough that unpack is ok
            "lt" -> return '<'
            "gt" -> return '>'
            "amp" -> return '&'
            "quot" -> return '"'
            '#' : 'x' : hex -> readHexChar hex
            '#' : 'X' : hex -> readHexChar hex
            '#' : dec -> readDecChar dec
            _ -> Nothing -- just to shut up a warning
        return $ c `SL.cons` decodeHtml after
    Just (x, xs) -> x `SL.cons` decodeHtml xs

readHexChar :: String -> Maybe Char
readHexChar s = helper 0 s where
    helper i "" = return $ toEnum i
    helper i (c:cs) = do
        c' <- hexVal c
        helper (i * 16 + c') cs

hexVal :: Char -> Maybe Int
hexVal c
    | '0' <= c && c <= '9' = Just $ ord c - ord '0'
    | 'A' <= c && c <= 'F' = Just $ ord c - ord 'A' + 10
    | 'a' <= c && c <= 'f' = Just $ ord c - ord 'a' + 10
    | otherwise = Nothing

readDecChar :: String -> Maybe Char
readDecChar s = do
    case reads s of
        (i, _):_ -> Just $ toEnum (i :: Int)
        _ -> Nothing
导入数据。可能吧
将符合条件的Web.Encodings.StringLike导入为SL
导入Web.Encodings.StringLike(StringLike)
导入数据字符(ord)
--|将HTML编码的内容解码为普通内容。
--
--注意:这不支持所有可用的HTML实体。它还吞咽
--所有的失败。
解码HTML::StringLike s=>s->s
解码HTML s=案例SL.UNCON s of
无->SL.empty
Just('&',xs)->fromMaybe('&'`SL.cons`decode html xs)$do
(之前、之后)返回'>'
“amp”->返回“&”
“quot“->返回”
“#”:“x”:十六进制->读取十六进制字符十六进制
“#”:“X”:十六进制->读取十六进制字符十六进制
“#”:dec->readDecChar dec
_->没什么--只是为了停止警告
之后返回$c`SL.cons`decodeHtml
只需(x,xs)->x`SL.cons`decodeHTMLxs
readHexChar::String->Maybe Char
readHexChar s=helper 0 s其中
helper i”“=返回$toEnum i
助手i(c:cs)=do

这是我的版本。它使用String(而不是ByteString)


我猜它更快,因为它不使用昂贵的正则表达式操作。我还没有测试过。如果需要更快的速度,您可以将其调整为ByteString或Data.Text。

这是我的版本。它使用String(而不是ByteString)


我猜它更快,因为它不使用昂贵的正则表达式操作。我还没有测试过。您可以将其调整为ByteString或Data.Text(如果您需要更快的话)。

现在还不清楚您的实际问题是什么。你在寻找更好的解决方案吗?需要帮助改进当前版本吗?如果问题不清楚,请道歉。是的,我想要一个更好的解决方案,因为我的是1。太慢了。使用的正则表达式似乎不是Haskell惯用的(因为关于它们的信息很少)。我的解决方案主要是作为一个“这就是我到目前为止得到的”出发点给出的。我对激进的想法持开放态度。你怎么看这份文件?如果我使用
main=Data.ByteString.interactive unescapeEntites
并使用
time cat big.txt |/regex>/dev/null
我可以获得143M big.txt的30秒时间(这是Tagsoop中列出的所有实体,中间有很多“a”)。从所有这些间接的过程中仍然很笨拙,但不是几分钟。不清楚你真正的问题是什么。你在寻找更好的解决方案吗?需要帮助改进当前版本吗?如果问题不清楚,请道歉。是的,我想要一个更好的解决方案,因为我的是1。太慢了。使用的正则表达式似乎不是Haskell惯用的(因为关于它们的信息很少)。我的解决方案主要是作为一个“这就是我到目前为止得到的”出发点给出的。我对激进的想法持开放态度。你怎么看这份文件?如果我使用
main=Data.ByteString.interactive unescapeEntites
并使用
time cat big.txt |/regex>/dev/null
我可以获得143M big.txt的30秒时间(这是Tagsoop中列出的所有实体,中间有很多“a”)。从这些间接的动作中仍然笨重,但不是几分钟。