JS實現HTML實體與字符的相互轉換(一)

最近在用Node.js獲取網頁時發現返回的網頁中有一些實體字符,比如中文應該是“用戶名”,結果返回的是用户名,讀起來相當不爽,於是網上查詢能將html實體字符轉化爲相應字符的方法,找了一些感覺不對症(不知道我是不是沒找對地方)。不多幸好知道了實體字符也是相應Unicode字符的再包裝,於是自己寫了js代碼來完成二者之間的相互轉換。

不過還是要澄清一下,本文主要講述的轉換不適用於所有的命名實體,如&nbsp;&amp;等,而僅僅是針對實體編號(包括10進制和16進制編碼)的,比如“中國”被編碼爲&#20013;&#22269;的情況。如果讓您失望了,在此我深表遺憾。不過,我的另一篇文章JS實現HTML實體與字符的相互轉換(二)將主要講述命名實體同字符的轉換,如&lt;<的相互轉換,希望能解決您的問題吧。

在講實體字符與相應字符之前的轉換前,首先再來複習一遍charCodeAtformCharCode兩個函數。前者是所有字符串共有的方法(定義在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('&#x7528;&#x6237;&#x540D;&#162;')
entityToString(stringToEntity(_str))
entityToString(stringToEntity(_str,1))
console.log('')
_str=entityToString('&#913;&#914;&#922;')
entityToString(stringToEntity(_str))
entityToString(stringToEntity(_str,1))
/******* the result *******
'&#x7528;&#x6237;&#x540D;&#162;' 轉字符串爲 '用戶名¢'
'用戶名¢' 轉實體爲 '&#29992;&#25143;&#21517;&#162;'
'&#29992;&#25143;&#21517;&#162;' 轉字符串爲 '用戶名¢'
i'用戶名¢' 轉實體爲 '&#x7528;&#x6237;&#x540d;&#xa2;'
'&#x7528;&#x6237;&#x540d;&#xa2;' 轉字符串爲 '用戶名¢'

'&#913;&#914;&#922;' 轉字符串爲 'ΑΒΚ'
'ΑΒΚ' 轉實體爲 '&#913;&#914;&#922;'
'&#913;&#914;&#922;' 轉字符串爲 'ΑΒΚ'
'ΑΒΚ' 轉實體爲 '&#x391;&#x392;&#x39a;'
'&#x391;&#x392;&#x39a;' 轉字符串爲 'ΑΒΚ'
**************************/

什麼,代碼有點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特殊符號對照表、常用的字符實體

發佈了21 篇原創文章 · 獲贊 27 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章