fast-xml-parser
项目的配置文件使用了xml配置文件,最初我使用的是fast-xml-parser。
对这个package我也比较熟悉,之前做xml解析的时候,因为项目需求,仔细拜读了源码,纯js实现的一个xml解析库。
放到creator3.x中使用有点小问题,如果直接导入,是undefined,至于原因,可能跟js的规范有关,这里没有深究
import {XMLParser} from 'fast-xml-parser'
console.log(XMLParser); // undefined
想要正常使用,需要这么转一下
import * as fastXmlParser from 'fast-xml-parser'
const XMLParser: typeof fastXmlParser.XMLParser = fastXmlParser.default.XMLParser;
测试发现fast-xml-parser在native上无法正常使用,造成了崩溃,出现了空指针
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 4099 (Thread-9), pid 4023
DOMParser
后来我突然想到,tiledmap也是使用的xml配置文件,engine是如何解析的呢?追了下源码
这个SAXParser
就是DOMParser
解析时调用的是
字符编码的问题
如下的assets/resources/test.xml文件
<?xml version="1.0" encoding="utf-8"?><root></root>
使用creator加载并使用DOMParser解析
resources.load('test', (error, asset:TextAsset)=>{
if(error) return;
const dom = new DOMParser();
const doc = dom.parseFromString(asset.text, "text/xml");
})
解析后竟然报错:
XML declaration allowed only at the start of the document
意思就是<?xml ?>
必须出现在第一行,我的xml文件的确是第一行,为什么报这个错误呢?
这个问题只发生在creator编辑器预览,在浏览器预览是正常的。最初我怀疑可能是parseFromString
的第二个参数导致,反复尝试都没解决。
可能是xml内容的问题?于是写了如下的神奇代码:
const text = `<?xml version="1.0" encoding="utf-8"?><root></root>`;
if (asset.text === text) {
// 竟然无法命中
}
凭肉眼的确看不出这个字符串有啥区别,很有可能是字符编码的问题,尝试比较了下长度
text.length;//51
asset.text.length; //52,很明显,这里就是多了一个字符串
asset.text.charCodeAt(0) // 65279 => 0xFEFF
asset.text.charCodeAt(1) // 60
xmlText.charCodeAt(0) // 60
FEFF
字节顺序标记(英语:byte-order mark,BOM)是位于码点U+FEFF的统一码字符的名称。当以UTF-16或UTF-32来将UCS/统一码字符所组成的字符串编码时,这个字符被用来标示其字节序。
asset.text
中的第一个字符是一个 Unicode 字符 U+FEFF
,也就是所谓的 "零宽度非换行空格"(Zero-Width No-Break Space),这个字符通常是不可见的,但是它可以影响字符串的比较。
在浏览器中,由于浏览器的 Unicode 处理方式,asset.text
和 text
可能会被视为相等。
但是,在 Node.js 中,由于 Node.js 的 Unicode 处理方式,asset.text
和 text
不会被视为相等。
为了解决这个问题,你可以使用以下方法来移除
const text = asset.text.replace(/\ufeff/g, '');