最近在用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特殊符号对照表、常用的字符实体