如何去除Tally XML科目导出响应中的特殊字符
解决C#反序列化Tally XML时的0x04无效字符问题
反序列化Tally导出的科目XML响应时,出现XmlException: '', 十六进制值0x04是无效字符错误,根源是<PARENT>元素中包含(对应ASCII控制字符0x04)——这类控制字符不符合XML规范,导致反序列化失败。以下是几种可行的解决方法:
方法一:预处理XML字符串,过滤无效控制字符
先读取响应内容为字符串,通过正则表达式移除XML不允许的控制字符(仅保留制表符、换行、回车),再进行反序列化:
var responseContent = await response.Content.ReadAsStringAsync(); // 过滤XML无效控制字符(0x00-0x08、0x0B、0x0C、0x0E-0x1F) var cleanedContent = Regex.Replace(responseContent, @"[\x00-\x08\x0B\x0C\x0E-\x1F]", string.Empty); // 使用清理后的内容创建流反序列化 using var stream = new MemoryStream(Encoding.UTF8.GetBytes(cleanedContent)); XmlSerializer serializer = new XmlSerializer(typeof(Ledgers)); var ledgers = (Ledgers?)serializer.Deserialize(stream);
方法二:自定义XmlTextReader处理无效字符
创建继承自XmlTextReader的自定义阅读器,在读取元素文本时过滤无效字符,避免修改整个XML结构:
public class CleanXmlReader : XmlTextReader { public CleanXmlReader(Stream stream) : base(stream) { } public override string ReadString() { var rawValue = base.ReadString(); // 移除文本中的无效控制字符 return Regex.Replace(rawValue, @"[\x00-\x08\x0B\x0C\x0E-\x1F]", string.Empty); } }
使用自定义阅读器反序列化:
using var stream = await response.Content.ReadAsStreamAsync(); using var cleanReader = new CleanXmlReader(stream); XmlSerializer serializer = new XmlSerializer(typeof(Ledgers)); var ledgers = (Ledgers?)serializer.Deserialize(cleanReader);
方法三:从源头修改Tally导出配置(优先推荐)
如果有权限调整Tally的导出TDL,可以直接在获取Parent字段时过滤特殊字符,从根源避免无效字符输出:
<FIELD ISMODIFY="NO" ISFIXED="NO" ISINITIALIZE="NO" ISOPTION="NO" ISINTERNAL="NO" NAME="CA_PARENT"> <SET>$PARENT</SET> <!-- 添加控制字符过滤逻辑 --> <FORMAT>$$Str:Replace($PARENT, Chr(4), "")</FORMAT> <XMLTAG>PARENT</XMLTAG> </FIELD>
总结
- 若能修改Tally的TDL配置,优先选择方法三,从源头解决问题;
- 无法修改导出配置时,方法一和方法二均可有效过滤无效字符,确保反序列化正常执行。
内容的提问来源于stack exchange,提问作者Ammar Haider
相关产品推荐
相关产品推荐

