【问题标题】:Hexadecimal value 0x00 is a invalid character十六进制值 0x00 是无效字符
【发布时间】:2012-06-17 16:54:43
【问题描述】:

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

string.Format("<text><row>{0}</row><col>{1}</col><textHeight>{2}</textHeight><textWidth>{3}</textWidth><data>{4}</data><rotation>{5}</rotation></text>

稍后,类似:

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

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

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

但它并不一致。 有时一些“空白”数据会起作用。 “错误”数据在某些 PC 上有效,但在其他 PC 上无效。

在数据库中,数据总是一个空字符串。它永远不是“空” 在 XML 文件中,它显示为 &lt; data&gt;&lt; /data&gt;,即在打开和关闭之间没有字符。 (但不确定这是否可以依赖,因为我将它从“即时”窗口中拉出并粘贴到 textpad 中)。

sql server 的版本(2008 会失败,2005 会工作)和排序规则也可能存在差异。 不确定这些是否是可能的原因?

但完全相同的代码和数据有时会失败。有什么想法吗?

【问题讨论】:

  • 真的是&lt; data&gt;&lt; /data&gt;在'后面有一个空格吗?如果是这样,您的 XML 已损坏且无法信任。丢弃它。全部。
  • @DourHighArch 我发现唯一可靠的方法就是烧掉它。

标签: .net sql-server xml


【解决方案1】:

如果没有您的实际数据或来源,我们将很难诊断出问题所在。不过,我可以提出一些建议:

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

鉴于您所写的内容,我怀疑将数据库数据转换为 XML 的任何内容都已损坏;它正在传播非 XML 字符。

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

如果转换器输出看起来不错,则问题出在您的 XML 使用者;它在某处插入非 XML 字符。您必须将您的消费过程分解为单独的步骤,检查每个步骤的输出,并缩小引入不良字符的范围。

检查文件编码(对于 UTF-16)

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

【讨论】:

  • 这里 UTF-16 问题的好技巧:stackoverflow.com/questions/26330578/…
  • 在我粘贴到配置文件之前,我使用"" &gt; myConfigFile.xml 在powershell 中为我的Web 应用程序创建了一个配置.xml 文件来初始化空文件后得到了这个。这将默认编码设置为 UTF-16...
  • 我刚刚遇到了这个问题:对我来说,问题是我正在使用 System.Encoding.Unicode.GetBytes("some string") 解析一个字符串。当我更改为 System.Encoding.Utf8.GetBytes("some string") 时开始工作。 YMMV。
【解决方案2】:

当我在 Web.config 文件中保存一些 unicode 数据(印地语)并使用“Unicode”编码保存时,我在 ASP.NET 应用程序中也遇到了同样的错误。

当我使用“UTF-8”编码保存 Web.config 文件时,它为我修复了错误。

【讨论】:

    【解决方案3】:

    就我而言,它需要一些挖掘,但找到了。

    我的背景

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

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

    非解决方案:我将文档转换为 byte[] 并将其清理为 0x00,但没有找到。

    扫描xml文档时,发现如下:

    ...
    <form>
    ...
    <item name="SomeField">
       <value
         string="C:\boot.ini&#x0;.htm" />
     </item>
    ...
    

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

    解决方案: 为了修复编码,我在将 &amp;#x0; 值加载到我的 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();
    }
    

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

    【讨论】:

      【解决方案4】:

      作为一种迟到的答案:

      我在上传报告时遇到了 SSRS ReportService2005.asmx 的问题。

          Public Shared Sub CreateReport(ByVal strFileNameAndPath As String, ByVal strReportName As String, ByVal strReportingPath As String, Optional ByVal bOverwrite As Boolean = True)
              Dim rs As SSRS_2005_Administration_WithFOA = New SSRS_2005_Administration_WithFOA
              rs.Credentials = ReportingServiceInterface.GetMyCredentials(strCredentialsURL)
              rs.Timeout = ReportingServiceInterface.iTimeout
              rs.Url = ReportingServiceInterface.strReportingServiceURL
              rs.UnsafeAuthenticatedConnectionSharing = True
      
              Dim btBuffer As Byte() = Nothing
      
              Dim rsWarnings As Warning() = Nothing
              Try
                  Dim fstrStream As System.IO.FileStream = System.IO.File.OpenRead(strFileNameAndPath)
                  btBuffer = New Byte(fstrStream.Length - 1) {}
                  fstrStream.Read(btBuffer, 0, CInt(fstrStream.Length))
                  fstrStream.Close()
              Catch ex As System.IO.IOException
                  Throw New Exception(ex.Message)
              End Try
      
              Try
                  rsWarnings = rs.CreateReport(strReportName, strReportingPath, bOverwrite, btBuffer, Nothing)
      
                  If Not (rsWarnings Is Nothing) Then
                      Dim warning As Warning
                      For Each warning In rsWarnings
                          Log(warning.Message)
                      Next warning
                  Else
                      Log("Report: {0} created successfully with no warnings", strReportName)
                  End If
      
              Catch ex As System.Web.Services.Protocols.SoapException
                  Log(ex.Detail.InnerXml.ToString())
              Catch ex As Exception
                  Log("Error at creating report. Invalid server name/timeout?" + vbCrLf + vbCrLf + "Error Description: " + vbCrLf + ex.Message)
                  Console.ReadKey()
                  System.Environment.Exit(1)
              End Try
          End Sub ' End Function CreateThisReport
      

      当您分配的字节数组至少比 RDL (XML) 文件大 1 个字节时,就会出现此问题。

      具体来说,我使用了一个 C# 到 vb.net 的转换器,它转换了

        btBuffer = new byte[fstrStream.Length];
      

      进入

        btBuffer = New Byte(fstrStream.Length) {}
      

      但是因为在 C# 中数字表示数组中的元素数量,而在 VB.NET 中,该数字表示数组的 UPPER BOUND,所以我有一个多余的字节,导致了这个错误。

      所以问题的解决方法很简单:

        btBuffer = New Byte(fstrStream.Length - 1) {}
      

      【讨论】:

        【解决方案5】:

        要添加到上面 Sonz 的答案,以下对我们有用。

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

        【讨论】:

        • 在从 Outlook 邮件项目中获取 RTF 正文并尝试将其序列化为 XML 后,这对我有用
        • 在对话中添加更多内容 .. 如果您必须跨越设备平台,消费设备需要您发送 并且您使用 xslt 转换为目标格式.. 您可以使用像 这样的占位符(您可以将其命名为任何名称)并在发送之前将其替换为最后。
        • 在我的情况下是 & #x0; ;数据存在于 XML 中,因此它没有被解析。我删除了它并更新了 XML 并修复了解析。
        【解决方案6】:

        我在这里使用 IronPython(与 .NET API 相同)并以 UTF-8 格式读取文件,以便正确处理 BOM,为我解决了这个问题:

        xmlFile = Path.Combine(directory_str, 'file.xml')
        doc = XPathDocument(XmlTextReader(StreamReader(xmlFile.ToString(), Encoding.UTF8)))
        

        它也适用于XmlDocument

        doc = XmlDocument()
        doc.Load(XmlTextReader(StreamReader(xmlFile.ToString(), Encoding.UTF8)))
        

        【讨论】:

          【解决方案7】:

          我有同样的问题,当我尝试保存文件时,整个代码是完美的,但在最后一个过程中,出现以下错误消息: "'.',十六进制值 0x00 是无效字符。"

          1.查看开发工具,我发现分配给工作表集合 {Hoja1}、{Cartera}、{JennyG、{MariaD、...

          2.然后我看到工作表名称中的最后一个字符“}”应该丢失到算法过程中从数据表对象分配工作表名称的任何时间。

          3.在Name属性上,工作表的真实名称是“MariaD\0\0\0\0\0\0\0\0\0\0\0\0\0\0”,隐藏不支持属性名称中的字符“\0”。

          4.最后,解决方法是将所有工作表名称中的当前字符替换为“”空字符串。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-11-14
            • 2016-03-30
            • 1970-01-01
            • 1970-01-01
            • 2018-12-02
            • 2016-08-05
            相关资源
            最近更新 更多