十六进制值0x00是无效字符

jb.*_*jb. 26 .net xml sql-server

我正在从StringBuilder生成XML文档,基本上类似于:

string.Format("<text><row>{0}</row><col>{1}</col><textHeight>{2}</textHeight><textWidth>{3}</textWidth><data>{4}</data><rotation>{5}</rotation></text>
Run Code Online (Sandbox Code Playgroud)

后来,像:

XmlDocument document = new XmlDocument();
document.LoadXml(xml);
XmlNodeList labelSetNodes = document.GetElementsByTagName("labels");
for (int index = 0; index < labelSetNodes.Count; index++)
{
    //do something
}
Run Code Online (Sandbox Code Playgroud)

所有数据都来自数据库.最近我遇到了一些错误问题:

十六进制值0x00是无效字符,第1行,位置nnnnn

但它不一致.有时候一些"空白"数据会起作用."有缺陷"的数据适用于某些PC,但不适用于其他PC.

在数据库中,数据始终是空字符串.它永远不会是'null',在XML文件中,它就是< data>< /data>,即打开和关闭之间没有字符.(但不确定这是否可以依赖,因为我从'直接'窗口拉出它是vis studio并将其粘贴到textpad中).

sql server的版本可能存在差异(2008年它将失败,2005年将会运行)和排序规则.不确定这些是否可能是原因造成的?

但完全相同的代码和数据有时会失败.问题所在的任何想法?

Dou*_*rch 26

没有您的实际数据或来源,我们很难诊断出现了什么问题.但是,我可以提出一些建议:

  • Unicode NUL(0x00)在所有XML版本中都是非法的,验证解析器必须拒绝包含它的输入.
  • 尽管如此; 真实的未经验证的XML可以包含任何可以想象的垃圾形成的字节.
  • XML 1.1允许零宽度和非打印控制字符(NUL除外),因此您无法在文本编辑器中查看XML 1.1文件并告诉它包含哪些字符.

鉴于你所写的内容,我怀疑将数据库数据转换为XML的任何内容都被破坏了; 它传播非XML字符.

使用非XML字符(NUL,DEL,控制字符等)创建一些数据库条目,并在其上运行XML转换器.将XML输出到文件并在十六进制编辑器中查看它.如果这包含非XML字符,则转换器会中断.修复它,或者,如果不能,则创建一个拒绝具有此类字符的输出的预处理器.

如果转换器输出看起来不错,那么问题在于您的XML使用者; 它在某处插入非XML字符.您必须将您的消费过程分解为单独的步骤,检查每一步的输出,并缩小引入坏字符的内容.

更新:我自己刚刚遇到了一个例子!发生的事情是,生产者将XML编码为UTF16,消费者期待UTF8.由于UTF16使用0x00作为所有ASCII字符的高字节而UTF8不使用,因此消费者将每个第二个字节视为NUL.在我的情况下,我可以更改编码,但建议所有XML有效负载都以BOM开头.


son*_*njz 12

在我的情况下,它需要一些挖掘,但发现它.

我的背景

我正在使用Elmah查看网站上的异常/错误日志.Elmah以大型XML文档的形式返回异常时的服务器状态.对于我们的报告引擎,我使用XmlWriter打印XML.

在网站攻击期间,我注意到有些xmls没有解析并且正在接收此'.', hexadecimal value 0x00, is an invalid character.异常.

不分辨率:我将文档转换为a byte[]并清理了0x00,但没有找到.

当我扫描xml文档时,我发现了以下内容:

...
<form>
...
<item name="SomeField">
   <value
     string="C:\boot.ini&#x0;.htm" />
 </item>
...
Run Code Online (Sandbox Code Playgroud)

将nul字节编码为html实体&#x0;!

解决方案:为了修复编码,我在将&#x0;值加载到my之前替换了它XmlDocument,因为加载它会创建nul字节,并且很难从对象中清除它.这是我的整个过程:

XmlDocument xml = new XmlDocument();
details.Xml = details.Xml.Replace("&#x0;", "[0x00]");  // in my case I want to see it, otherwise just replace with ""
xml.LoadXml(details.Xml);

string formattedXml = null;

// I have this in a helper function, but for this example I have put it in-line
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings {
    OmitXmlDeclaration = true,
    Indent = true,
    IndentChars = "\t",
    NewLineHandling = NewLineHandling.None,
};
using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
    xml.Save(writer);
    formattedXml = sb.ToString();
}
Run Code Online (Sandbox Code Playgroud)

经验教训:如果您的传入数据在输入时进行了html编码,则使用关联的html实体清理非法字节.


小智 6

为了增加Sonz上面的答案,以下为我们工作.

//Instead of 
XmlString.Replace("&#x0;", "[0x00]");
// use this
XmlString.Replace("\x00", "[0x00]");
Run Code Online (Sandbox Code Playgroud)