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

Posted

技术标签:

【中文标题】xml.LoadData - 根级别的数据无效。第 1 行,位置 1【英文标题】:xml.LoadData - Data at the root level is invalid. Line 1, position 1 【发布时间】:2013-07-21 15:16:00 【问题描述】:

我正在尝试在 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,以便查看是否有任何错误。

【问题讨论】:

@marc_s:string 真的可以是 UTF-8 吗?如果在加载之前删除处理指令(第一行)怎么办? 如果我获取您的代码并编译并运行它,我不会收到任何错误。但这可能是因为我填充了 myString 硬编码。您的 myString 是如何设置的?如果它来自另一个文件或流,则文件顶部的字节顺序标记可能会令人讨厌。编辑器通常不会显示它(除非他们有十六进制模式)。 它似乎在没有第一行的情况下解析。让我确保能够以这种方式处理错误。抱歉,拖了这么久。每次我想测试时,我都必须重新构建整个 WiX 安装程序。 @Richard - 它来自远程服务器的服务调用。 如果您在上面的文件中有任何内容:&lt;?xml version="1.0" encoding="utf-8"?&gt; 然后将其从文件中删除并重试。 【参考方案1】:

隐藏的字符可能是 BOM。 问题的解释和解决方案可以在here 中找到,归功于 James Schubert,基于 James Brankin 找到的here 的回答。

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

string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xml.StartsWith(_byteOrderMarkUtf8))

    xml = xml.Remove(0, _byteOrderMarkUtf8.Length);

我在从 Azure blob 获取 XSLT 文件并将其加载到 XslCompiledTransform 对象时遇到了这个问题。 在我的机器上,该文件看起来很好,但是在将其作为 blob 上传并取回后,添加了 BOM 字符。

【讨论】:

不确定,我想我必须继续寻找,但是当我这样做时 _byteOrderMarkUtf8 = ""。所以它不会抓住它。想法? 试过了,没用。 xml 来自 db Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()) 计算结果为空字符串 与上述评论者有同样的问题。使用xmlStartsWith(byteOrderMarkUtf8, StringComparison.Ordinal) 对我有用。感谢 Hans Passant:***.com/a/19495964/38425 这为我解决了这个问题,非常感谢,我已经为此苦苦挣扎了一段时间。【参考方案2】:

改用Load() 方法,它会解决问题。 See more

【讨论】:

我正在使用 XDocument.Load(),但我遇到了问题。 似乎 XmlDocument.Load() 在标题中指定文件编码时会处理文件编码。如果没有,可能需要处理 StreamReader 和 XmlDocument.LoadXml 等工具。【参考方案3】:

这里的问题是myString 有那个标题行。第一行的开头有一些隐藏字符,或者是该行本身导致了错误。我像这样切掉了第一行:

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

这解决了我的问题。

【讨论】:

一旦我收到此错误,结果是“?”一开始。我只是用一个空格替换它并让它运行......如果您正在阅读的文件的编码与您期望的不同,也可能会发生这种情况 我试过这个,但在 .NETPrehistoric (1.1) 中,我尝试使用“\r\n”代替当时不可用的 Environment.NewLine。我得到了,“指定的参数超出了有效值的范围。” @Chris:我已经尝试过您的解决方案。我越来越低于异常。 System.ArgumentOutOfRangeException:StartIndex 不能小于零。参数【参考方案4】:

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

我对根级别数据的解决方案无效。第 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 内容以进行解析或加载。

希望对你有帮助

【讨论】:

【参考方案5】:

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

文件 > 将文件另存为... > 另存为 UTF-8 不带签名。

在 VS 2017 中,您可以在“保存”按钮旁边找到编码作为下拉菜单。

【讨论】:

【参考方案6】:

我通过直接编辑字节数组解决了这个问题。 收集 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 与否。【参考方案7】:

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

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

【讨论】:

【参考方案8】:

起初我在转义“&”字符时遇到了问题,然后变音符号和特殊字母显示为问号,最后出现了 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 等)。 See more

【讨论】:

【参考方案9】:

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

使用 StreamReader 创建时将第二个构造函数参数 detectEncodingFromByteOrderMarks 设置为 true,将确定正确的编码并创建不会破坏 XmlDocument.LoadXml 方法的 string

public string GetXmlString(string url)

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

常见的错误是在streambyte[] 上盲目使用UTF8 编码。下面的代码会生成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`

【讨论】:

【参考方案10】:

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

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 方法重载具有编码参数的默认值(System.Text.Encoding 编码) 谢谢大佬指点,能否指正一下? 您应该使用 Encoding 类的方法对 String 进行解码和编码,根本不需要(也没有意义)使用 File 方法或文件系统。请检查:docs.microsoft.com/en-us/dotnet/api/…【参考方案11】:

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

【讨论】:

以上是关于xml.LoadData - 根级别的数据无效。第 1 行,位置 1的主要内容,如果未能解决你的问题,请参考以下文章

API Microsoft Translator 异常:“根级别的数据无效。第 1 行,位置 1。”

“根级别的数据无效。第 1 行,位置 1”解析 XML 时

C# XML 解析 - 根级别的数据无效。第 1 行,位置 1

web平台安装器 根级别上的数据无效.行1,位置1.

来自 URL 的 XML - 根级别的数据无效。第 1 行,位置 1 为啥它适用于一个 URL 而不是另一个?

System.Xml.XmlException '根级别的数据无效,第 1 行,位置 1' 当我从 1 个 xml 文件更改为 5 时出现错误