writeattributestring自动转义xml五种预定义实体,其他字符原样写入;非法字符(如\0)在.net 6+抛argumentexception;命名空间需用特定重载;不可混用writestartattribute;null/空字符串均输出attr=""。

WriteAttributeString 会自动转义特殊字符吗
会,但只转义 XML 标准定义的五个预定义实体:&、、<code>>、"、'。其他 Unicode 字符(比如中文、emoji、控制字符)原样写入,不编码也不报错。
常见错误现象:WriteAttributeString("name", "a & b <test>")</test> 输出为 name="a & b <test>"</test>,这是预期行为;但如果传入 \0 或 \x01,.NET 6+ 会抛 ArgumentException:“Invalid character in the given encoding”,因为 XML 规范禁止这些字符。
- 若需支持任意二进制数据,先 Base64 编码再写入,别指望
WriteAttributeString帮你处理 - 不要手动提前转义——比如把
&换成&再传进去,否则会被双重转义成& - .NET Core 3.1+ 对非法字符检查更严格,旧项目升级后可能突然报错
写命名空间属性要用 WriteAttributeString 吗
不能直接用。命名空间声明(如 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance")本质是特殊属性,但 WriteAttributeString 不识别 xmlns 前缀语义,它只会当成普通属性名写死,无法触发命名空间绑定逻辑。
正确做法是用 WriteAttributeString 的重载或配合 WriteStartElement:
- 写默认命名空间:用
WriteAttributeString("xmlns", "http://my.ns") - 写带前缀的命名空间:用
WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance") - 如果已调用
WriteStartElement("root", "http://my.ns"),后续元素自动继承该命名空间,无需重复声明
WriteAttributeString 和 WriteStartAttribute 配合使用行不行
不行,会抛 InvalidOperationException:“WriteStartAttribute cannot be called when the writer is in a state where an attribute can be written.”
WriteAttributeString 是原子操作,内部已封装了开始、写内容、结束三步;而 WriteStartAttribute 是低阶 API,必须配对 WriteString + WriteEndAttribute。混用会破坏写入器状态机。
- 99% 场景只用
WriteAttributeString,它简洁且安全 - 只有需要分段写入属性值(比如流式拼接、动态计算中间值)才考虑
WriteStartAttribute,但极少见 - 一旦调用
WriteStartAttribute,就不能在同级再调用任何WriteAttributeString
空字符串或 null 当作属性值会发生什么
null 会被当作空字符串处理,写入结果是 attr="";空字符串本身也输出为 attr=""。两者效果一致,不会跳过该属性,也不会报错。
但要注意:XML Schema 中若该属性声明为 use="required",空值仍算“存在”,只是内容为空——校验是否通过取决于 schema 定义,不是 XmlWriter 的责任。
- 别用
if (val != null) writer.WriteAttributeString(...)来“避免空属性”,这逻辑和业务意图往往不符 - 如果协议明确要求省略空属性,得自己判断:
if (!string.IsNullOrEmpty(val)) writer.WriteAttributeString(...) - 写入
val = " "(空格)会被保留,不会 trim,XML 层不负责空白归一化
最常被忽略的是字符合法性边界——不是所有能显示的字符串都合法,XmlWriter 在 close 时才做最终验证,出错时堆栈不指向 WriteAttributeString 调用点,而是指向 Close() 或 Dispose()。调试时得倒查最近写的属性值。










