我正在从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文件中,它以< data>< /data>
形式出现,即打开和关闭之间没有字符。 (但不确定这是否可以依赖,因为我从'立即'窗口拉出它是工作室并将其粘贴到文本板中。)
sql server的版本可能存在差异(2008年它将失败,2005年将会运行)和排序规则。 不确定这些是否可能是原因造成的?
但完全相同的代码和数据有时会失败。问题出在哪里?
答案 0 :(得分:23)
如果没有您的实际数据或来源,我们很难诊断出现了什么问题。但是,我可以提出一些建议:
鉴于你写的内容,我怀疑将数据库数据转换为XML的任何内容都被破坏了;它正在传播非XML字符。
使用非XML字符(NUL,DEL,控制字符等)创建一些数据库条目,并在其上运行XML转换器。将XML输出到文件并在十六进制编辑器中查看它。如果这包含非XML字符,则转换器会中断。修复它,或者,如果不能,则创建一个拒绝带有这些字符的输出的预处理器。
如果转换器输出看起来不错,则问题出在您的XML使用者身上;它在某处插入非XML字符。您必须将您的消费过程分解为单独的步骤,检查每一步的输出,并缩小引入坏字符的内容。
更新:我自己就是这样做的一个例子!发生的事情是,生产者将XML编码为UTF16,消费者期望UTF8。由于UTF16使用0x00作为所有ASCII字符的高字节而UTF8不使用,因此消费者将每个第二个字节视为NUL。在我的情况下,我可以更改编码,但建议所有XML有效负载都以BOM开头。
答案 1 :(得分:10)
在我的情况下,它花了一些挖掘,但发现了它。
我的情境
我正在使用Elmah查看网站上的异常/错误日志。 Elmah以大型XML文档的形式返回异常时的服务器状态。对于我们的报告引擎,我使用XmlWriter打印XML。
在网站攻击期间,我注意到有些xmls没有解析并且收到此'.', hexadecimal value 0x00, is an invalid character.
例外。
非解决方案:我将文档转换为byte[]
并将其清理为0x00,但没有找到。
当我扫描xml文档时,我发现了以下内容:
...
<form>
...
<item name="SomeField">
<value
string="C:\boot.ini�.htm" />
</item>
...
将nul字节编码为html实体�
!!!
解决方法:为了修复编码,我在将�
值加载到XmlDocument
之前替换了XmlDocument xml = new XmlDocument();
details.Xml = details.Xml.Replace("�", "[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();
}
值,因为加载它会创建nul字节,这将很难从物体上消毒它。这是我的整个过程:
{{1}}
经验教训:使用关联的html实体清理非法字节,如果您的传入数据在输入时进行了html编码。
答案 2 :(得分:6)
要添加Sonz的上述答案,以下是为我们工作的。
//Instead of
XmlString.Replace("�", "[0x00]");
// use this
XmlString.Replace("\x00", "[0x00]");
答案 3 :(得分:4)
当我在Web.config文件中保存了一些unicode数据(Hindi)并使用“Unicode”编码保存时,我在ASP.NET应用程序中也遇到了同样的错误。
当我使用“UTF-8”编码保存Web.config文件时,它修复了我的错误。
答案 4 :(得分:3)
作为一个迟到的回答:
上传报告时,我遇到了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#中数字表示数组中的NUMEMENT OF ELEMENTS,而在VB.NET中,该数字表示数组的UPPER BOUND,我有一个多余的字节,导致此错误。
所以问题的解决方案很简单:
btBuffer = New Byte(fstrStream.Length - 1) {}
答案 5 :(得分:1)
我在这里使用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)))
答案 6 :(得分:0)
我遇到了同样的问题,当我尝试保存文件时,整个代码是完美的,但在最后一个过程中,出现以下错误消息: "'.', 十六进制值 0x00 是无效字符。"
1.查看开发工具,我发现在分配给sheet collection {Hoja1}, {Cartera}, {JennyG, {MariaD, ...
2.然后我看到工作表名称中的最后一个字符 '}' 应该丢失到算法过程中的任何时间,以从 DataTable 对象分配工作表名称。
3.在Name属性上,工作表的真实名称是“MariaD\0\0\0\0\0\0\0\0\0\0\0\0\0\0”,隐藏的不支持属性名称中的字符“\0”。
4.最后,解决办法是将当前字符替换为所有工作表名称中的“”空字符串。