如何将拉丁基Unicode字符串转换为EDIFACT Level A精简编码?
EDIFACT Level A 编码转换:字符参考与实现方案
一、字符映射参考来源
- EDIFACT官方规范:Level A编码明确限定为大写A-Z、数字0-9,以及以下符号:
(空格)、!、"、%、&、'、(、)、*、+、,、-、.、/、:、;、<、=、>、?。所有带重音的拉丁字符需映射到对应的无重音基础字符。 - Unicode字符数据库(UCD):利用Unicode的标准化分解(Normalization Form D,NFD),可将任意带重音的拉丁字符拆分为「基础拉丁字符+独立重音标记」,过滤重音标记后即可得到无重音对应字符,无需手动维护全量带重音字符映射表。
- 预定义映射表:如果需要精准控制特定字符的转换,可整理欧洲主流语言的带重音字符映射(如
À→A、É→E、Ö→O等),覆盖常见场景。
二、实现方案(以C#为例)
核心思路
- 对输入字符串做Unicode NFD标准化,拆分带重音字符的基础部分与重音标记;
- 过滤掉所有重音标记类字符;
- 将剩余字符转为大写,检查是否属于Level A允许范围,非允许字符替换为
?。
代码实现
using System; using System.Collections.Generic; using System.Text; using System.Globalization; public static class EdifactLevelAConverter { // 定义EDIFACT Level A允许的所有字符 private static readonly HashSet<char> AllowedLevelAChars = new HashSet<char> { ' ', '!', '"', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; public static string ConvertToLevelA(string input) { if (string.IsNullOrWhiteSpace(input)) return string.Empty; // 转换为NFD格式,拆分重音与基础字符 var normalizedInput = input.Normalize(NormalizationForm.FormD); var resultBuilder = new StringBuilder(); foreach (var c in normalizedInput) { // 跳过非间距标记(即重音符号) if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) { var upperChar = char.ToUpperInvariant(c); // 检查是否在允许集合内,否则替换为? resultBuilder.Append(AllowedLevelAChars.Contains(upperChar) ? upperChar : '?'); } } return resultBuilder.ToString(); } }
方案优势
- 利用Unicode标准化自动处理所有带重音拉丁字符,无需手动枚举所有带重音变体;
- 代码简洁高效,覆盖所有符合要求的转换场景;
- 可直接扩展允许字符集合或添加特殊字符映射(如后续需要处理
ß→SS这类转录)。
三、注意事项
- 按照需求,暂不处理
Straße→STRASSE这类特殊转录,因此德语ß等非基础拉丁字符会被替换为?; - 非拉丁字符(如中文、日文等)直接替换为
?,符合需求中的信息损失但保持可读性的要求。
内容的提问来源于stack exchange,提问作者pepr
相关产品推荐
相关产品推荐

