xml.LoadData-根级别的数据无效。1号线,位置1


76

我正在尝试在WiX安装程序中解析一些XML。XML将是我从Web服务器返回的所有错误的对象。我收到以下代码的问题标题中的错误:

XmlDocument xml = new XmlDocument();
try
{
    xml.LoadXml(myString);
}
catch (Exception ex)
{
    System.IO.File.WriteAllText(@"C:\text.txt", myString + "\r\n\r\n" + ex.Message);
    throw ex;
}

myString这是(如的输出所示text.txt

<?xml version="1.0" encoding="utf-8"?>
<Errors></Errors>

text.txt 看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<Errors></Errors>

Data at the root level is invalid. Line 1, position 1.

我需要解析该XML,以便查看是否有任何错误。

编辑

此问题不是标记的重复项。在那个问题中,提出问题的人正在使用它LoadXml来解析XML文件。我正在解析一个字符串,这是正确的用法LoadXml


真的需要查看xml来提供帮助
RedEyedMonster

我已将其添加到问题中,但已经在的输出中text.txt
克里斯(Chris)

1
@JohnSaunders-这不是那个问题的重复。在该问题中,提出问题的人正在使用LoadXml解析XML文件。我正在解析一个字符串,这是的正确用法LoadXml
克里斯,

1
@marc_s:string真的可以成为UTF-8吗?如果在加载之前删除了处理指令(第一行)怎么办?
约翰·桑德斯

2
如果我采用您的代码并编译并运行它,则不会出错。但这也许是因为我填写了硬编码的myString。如何设置myString?如果它来自另一个文件或流,则在文件顶部可能会出现一些令人讨厌的字节顺序标记。通常编辑器不会显示它(除非他们具有十六进制模式)。
理查德

Answers:


118

隐藏的字符可能是BOM。在分析和解决问题的解释可以发现在这里,学分詹姆斯舒伯特的基础上,由詹姆斯·Brankin答案找到这里

尽管上一个答案确实删除了隐藏的字符,但它也删除了整个第一行。更精确的版本是:

string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xml.StartsWith(_byteOrderMarkUtf8))
{
    xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
}

从Azure blob提取XSLT文件并将其加载到XslCompiledTransform对象时遇到了此问题。在我的机器上,文件看起来还不错,但是在将其作为blob上传并取回后,添加了BOM字符。


3
不确定,我想我必须继续寻找,但是当我这样做时_byteOrderMarkUtf8 =“”。所以它没有抓住。有想法吗?
user1040975

1
尝试了一下,没有帮助。XML是从数据库来为此事
约翰DEMETRIOU

1
Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble())计算结果为空字符串
库克先生(Mister Cook)

6
与上述评论者存在相同的问题。使用xmlStartsWith(byteOrderMarkUtf8, StringComparison.Ordinal)帮了我大忙。
感谢

2
这为我解决了这个问题,非常感谢,我已经为此花了很长时间。
mknopf

62

使用Load()方法代替,它将解决问题。查看更多


15
我正在使用XDocument.Load(),但我遇到了问题。
B. Clay Shannon

1
因此,在标头中指定XmlDocument.Load()时,它会处理文件编码。如果不是这样,则可能不得不处理StreamReader和XmlDocument.LoadXml等工具。
CLS

14

这里的问题是myString标题行。第一行的开头有一些隐藏的字符,或者该行本身正在引起错误。我像这样切掉第一行:

xml.LoadXml(myString.Substring(myString.IndexOf(Environment.NewLine)));

这解决了我的问题。


4
一旦遇到此错误,结果就变成了“?” 在开始时。我只是将其替换为空白并使其运行...如果您正在读取的文件使用的编码与您期望的编码不同,也可能发生这种情况
Ricardo Appleton 2013年

我尝试了此操作,但是在.NETPrehistoric(1.1)中,我尝试使用“ \ r \ n”代替当时不可用的Environment.NewLine。我得到“指定的参数超出有效值范围。”
B. Clay Shannon

@克里斯:我已经尝试过您的解决方案。我在例外之下。System.ArgumentOutOfRangeException:StartIndex不能小于零。参数
Shesha

10

我认为问题在于编码。这就是为什么删除第一行(带有编码字节)可能会解决问题的原因。

在根级别的数据解决方案无效。第1行的位置1 中的XDocument.Parse(xmlString)替换为XDocument.Load( new MemoryStream( xmlContentInBytes ) );

我注意到我的xml字符串看起来不错:

<?xml version="1.0" encoding="utf-8"?>

但是在不同的文本编辑器中,编码看起来像这样:

?<?xml version="1.0" encoding="utf-8"?>

最后,我不需要xml字符串,而需要xml byte []。如果需要使用字符串,则应在字符串中查找“不可见”字节,并使用编码来调整xml内容以进行解析或加载。

希望对你有帮助


3

我已经通过直接编辑字节数组解决了这个问题。收集UTF8前同步码并直接删除标头。之后,您可以使用GetString方法将byte []转换为字符串,请参见下文。为了预防起见,我也删除了\ r和\ t。

XmlDocument configurationXML = new XmlDocument();
List<byte> byteArray = new List<byte>(webRequest.downloadHandler.data);

foreach(byte singleByte in Encoding.UTF8.GetPreamble())
{
     byteArray.RemoveAt(byteArray.IndexOf(singleByte));
}
string xml = System.Text.Encoding.UTF8.GetString(byteArray.ToArray());
       xml = xml.Replace("\\r", "");
       xml = xml.Replace("\\t", "");

它为我工作。但是在循环中,我们需要先检查byteArray.IndexOf(singleByte)!= -1或不删除它。
ThanhLD

2

使用不同的编码保存文件:

文件>将文件另存为...>另存为UTF-8(无签名)。

在VS 2017中,您可以在保存按钮旁边找到编码作为下拉列表。


2

最初,我在转义“&”字符时遇到问题,然后将变音符号和特殊字母显示为问号,最后出现提到的OP问题。

我查看了答案,并使用@Ringo的建议尝试使用Load()方法作为替代方法。这使我意识到我可以用其他方式处理我的响应,而不仅仅是字符串。

使用System.IO.Stream代替字符串为我解决了所有问题。

var response = await this.httpClient.GetAsync(url);
var responseStream = await response.Content.ReadAsStreamAsync();
var xmlDocument = new XmlDocument();
xmlDocument.Load(responseStream);

关于Load()的一个很酷的事情是该方法自动检测输入XML的字符串格式(例如,UTF-8,ANSI等)。查看更多


1

如果您的xml在字符串中,请使用以下命令删除任何字节顺序标记:

        xml = new Regex("\\<\\?xml.*\\?>").Replace(xml, "");

真的救了我的命。我已经尝试了所有建议,但是您的解决方案解决了我的问题。非常感谢你!
Tornike Gomareli

0

我找到了一种解决方案。对于您的代码,可能如下所示-

XmlDocument xml = new XmlDocument();
try
{
    // assuming the location of the file is in the current directory 
    // assuming the file name be loadData.xml
    string myString = "./loadData.xml";
    xml.Load(myString);
}
catch (Exception ex)
{
    System.IO.File.WriteAllText(@"C:\text.txt", myString + "\r\n\r\n" + ex.Message);
    throw ex;
}

这是一个解决方案,但不好。这是编码问题,通过写入和读取文件,您实际上不知道执行编码和解码,因为调用Load方法的重载具有Encoding参数的默认值(System.Text.Encoding encoding)
hardyVeles

谢谢您的先生指出,请您指正我吗?
Shubhasish Bhunia

您应该使用Encoding类的方法对String进行解码和编码,根本不需要(也没有必要)使用File方法或文件系统。请检查:docs.microsoft.com/en-us/dotnet/api/…–
hardyVeles

0

如果我们使用XDocument.Parse(@“”)。使用@可以解决问题。


0

导致此错误的主要原因是逻辑,该逻辑确定将数组Streambyte[]数组转换为.NET时的编码string

使用StreamReader将2nd构造函数参数detectEncodingFromByteOrderMarks设置为true的created可以确定正确的编码并创建string不中断XmlDocument.LoadXml方法。

public string GetXmlString(string url)
{
    using var stream = GetResponseStream(url);
    using var reader = new StreamReader(stream, true);
    return reader.ReadToEnd(); // no exception on `LoadXml`
}

常见的错误是仅UTF8streamor上盲目使用编码byte[]string当在Visual Studio调试器中检查或复制粘贴到某处时,下面的代码将产生看起来有效的代码,但是当与一起使用LoadLoadXml文件的编码方式与没有BOM的UTF8编码方式不同时,它将产生异常。

public string GetXmlString(string url)
{
    byte[] bytes = GetResponseByteArray(url);
    return System.Text.Encoding.UTF8.GetString(bytes); // potentially exception on `LoadXml`
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.