最近在用Node.js獲取網頁時發現返回的網頁中有一些實體字符,比如中文應該是“用戶名”,結果返回的是用户名
,讀起來相當不爽,於是網上查詢能將html實體字符轉化爲相應字符的方法,找了一些感覺不對症(不知道我是不是沒找對地方)。不多幸好知道了實體字符也是相應Unicode字符的再包裝,於是自己寫了js代碼來完成二者之間的相互轉換。
不過還是要澄清一下,本文主要講述的轉換不適用於所有的命名實體,如
、&
等,而僅僅是針對實體編號(包括10進制和16進制編碼)的,比如“中國”被編碼爲中国
的情況。如果讓您失望了,在此我深表遺憾。不過,我的另一篇文章JS實現HTML實體與字符的相互轉換(二)將主要講述命名實體同字符的轉換,如<
與<
的相互轉換,希望能解決您的問題吧。
在講實體字符與相應字符之前的轉換前,首先再來複習一遍charCodeAt
和formCharCode
兩個函數。前者是所有字符串共有的方法(定義在String.prototype中),它接收一個參數,可返回指定位置字符的 Unicode 編碼,這個返回值是 0 - 65535 之間的整數;後者是String的靜態方法,可接受一個或多個指定的 Unicode 值,然後返回一個字符串。好了,知道這兩個函數就能完成Unicode值與字符的相互轉換了。還是來看代碼:
//字符串轉字符實體
function stringToEntity(str,radix){
let arr=[]
//返回的字符實體默認10進制,也可以選擇16進制
radix=radix||0
for(let i=0;i<str.length;i++){
arr.push((!radix?'&#'+str.charCodeAt(i):'&#x'+str.charCodeAt(i).toString(16))+';')
}
let tmp=arr.join('')
console.log(`'${str}' 轉實體爲 '${tmp}'`)
return tmp
}
這裏沒什麼好講的,就是用charCodeAt
函數把字符串的Unicode碼返回再加上實體符號的前綴後綴,拼接就好了。
//字符實體轉字符串
function entityToString(entity){
let entities=entity.split(';')
entities.pop()
let tmp=''
for(let i=0;i<entities.length;i++){
let num=entities[i].trim().slice(2)
if(num[0]==='x')//10進制還是16進制
num=parseInt(num.slice(1),16);
else num=parseInt(num);
tmp+=String.fromCharCode(num)
}
console.log(`'${entity}' 轉字符串爲 '${tmp}'`)
return tmp
}
這個也好理解,提取出給定實體的Unicode字符碼,用String.fromCharCode
轉換爲給定的字符就好了。關鍵把位置找好。
這裏用到了一些ES6的語法,比如let
和模版字符串(就是寫在反引號裏面的東西了,減輕了我們拼接字符串的負擔)語法。還有後面的箭頭函數都是很好的東西,但有時也會踩坑呀。整體思想還是挺簡單的,就是字符轉Unicode碼然後按相應格式拼接就可以了。
然後測試一下效果,嗯,效果還是不錯的
let _str=entityToString('用户名¢')
entityToString(stringToEntity(_str))
entityToString(stringToEntity(_str,1))
console.log('')
_str=entityToString('ΑΒΚ')
entityToString(stringToEntity(_str))
entityToString(stringToEntity(_str,1))
/******* the result *******
'用户名¢' 轉字符串爲 '用戶名¢'
'用戶名¢' 轉實體爲 '用户名¢'
'用户名¢' 轉字符串爲 '用戶名¢'
i'用戶名¢' 轉實體爲 '用户名¢'
'用户名¢' 轉字符串爲 '用戶名¢'
'ΑΒΚ' 轉字符串爲 'ΑΒΚ'
'ΑΒΚ' 轉實體爲 'ΑΒΚ'
'ΑΒΚ' 轉字符串爲 'ΑΒΚ'
'ΑΒΚ' 轉實體爲 'ΑΒΚ'
'ΑΒΚ' 轉字符串爲 'ΑΒΚ'
**************************/
什麼,代碼有點low,那好吧,這樣呢?這樣就簡潔多了。
function stringToEntity(str,radix){
let arr=str.split('')
radix=radix||0
let tmp=arr.map(item=>
`&#${(radix?'x'+item.charCodeAt(0).toString(16):item.charCodeAt(0))};`).join('')
console.log(`'${str}' 轉實體爲 '${tmp}'`)
return tmp
}
function entityToString(entity){
let entities=entity.split(';')
entities.pop()
let tmp=entities.map(item=>String.fromCharCode(
item[2]==='x'?parseInt(item.slice(3),16):parseInt(item.slice(2)))).join('')
console.log(`'${entity}' 轉字符串爲 '${tmp}'`)
return tmp
}
下面給一個HTML實體對照表:
HTML特殊符號對照表、常用的字符實體