如何从XML Unicode字符数据库提取Unicode规范化表?属性选择困惑
解决Unicode规范化表构建的属性选择问题
首先,你找错属性组啦!NF(C|D|KC|KD)_QC 这类属性的作用正如你所说,只是快速判断字符串是否已经符合对应规范化形式,它们不会给出具体的码点映射关系,用来构建规范化表肯定行不通。
要构建Unicode规范化(比如NFD、NFC、NFKD、NFKC)所需的映射表,你需要关注以下这些核心属性和数据文件:
1. 规范化分解与组合的核心属性
- Canonical Decomposition(
Canonical_Combining_Class+Decomposition_Mapping)Canonical_Combining_Class:决定字符的组合顺序,非0值表示该字符是组合字符,需要和前面的基字符组合。Decomposition_Mapping:这才是你需要的核心属性!它会给出字符的规范化分解结果——比如带重音的字符会分解为基字符+重音符号,或者兼容字符分解为对应的标准字符(比如全角数字分解为半角数字)。- 注意:
Decomposition_Mapping里的<compat>标记对应NFKD/NFKC的兼容分解,没有标记的是NFD/NFC的规范分解。
- Canonical Composition Exclusions:有些字符虽然可以分解,但不会被反向组合(比如某些特殊的带重音字符),这个列表需要用来处理NFC/NFKC的组合逻辑。
2. 大小写折叠的相关属性
如果你的脚本还包含大小写折叠功能,除了常见的Lowercase_Mapping、Uppercase_Mapping、Titlecase_Mapping,还要注意:
Case_Folding属性:它提供了更全面的大小写映射,包括一些特殊语言的折叠规则(比如德语的ß对应SS,或者土耳其语的I/i规则),比单纯的上下映射更适合做大小写折叠表。
3. 获取这些属性的正确方式
你不需要自己从UAX#44里抠属性定义,直接用Unicode官方提供的UnicodeData.txt和CaseFolding.txt这两个数据文件就够了:
UnicodeData.txt:包含了所有字符的Decomposition_Mapping、Canonical_Combining_Class、上下映射等核心属性,每一行是一个字符的完整数据,用分号分隔。CaseFolding.txt:专门存放大小写折叠的映射规则,包含简单折叠和全折叠两种类型。
举个C语言处理的简化示例,读取UnicodeData.txt时可以按分号分割字段,提取关键信息:
// 示例:解析UnicodeData.txt的一行(简化版) char line[1024]; FILE *fp = fopen("UnicodeData.txt", "r"); if (!fp) { /* 处理文件打开失败 */ } while (fgets(line, sizeof(line), fp)) { char *token = strtok(line, ";"); int field_idx = 0; char code_point[10], decomp_mapping[256], combining_class[10]; while (token != NULL) { switch(field_idx) { case 0: strncpy(code_point, token, sizeof(code_point)-1); break; // 字符码点 case 2: strncpy(combining_class, token, sizeof(combining_class)-1); break; // 组合类 case 4: strncpy(decomp_mapping, token, sizeof(decomp_mapping)-1); break; // 分解映射 } field_idx++; token = strtok(NULL, ";"); } // 这里可以处理分解映射:判断是否带<compat>标记,提取分解后的码点列表等 } fclose(fp);
最后总结
你之前的问题就是误把“规范化检查属性”当成了“规范化映射属性”,换用Decomposition_Mapping、Canonical_Combining_Class这些属性,再结合官方的Unicode数据文件,就能顺利构建出你需要的规范化和大小写折叠表啦。
内容的提问来源于stack exchange,提问作者user4302383




