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

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

提问人:Chris 提问时间:7/23/2013 最后编辑:TylerHChris 更新时间:1/9/2023 访问量:325972

问:

我正在尝试解析 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来解析,这样我就可以看看我是否有任何错误。

C# XML 解析 Wix

评论

1赞 John Saunders 7/23/2013
@marc_s:a 真的可以是 UTF-8 吗?如果在加载之前删除了处理指令(第一行)怎么办?string
2赞 Richard 7/23/2013
如果我获取您的代码并编译并运行它,我不会收到任何错误。但这可能是因为我填充了硬编码的 myString。你的 myString 是如何设置的?如果它来自另一个文件或流,则文件顶部的字节顺序标记可能会令人讨厌。它通常不会被编辑器显示(除非它们具有十六进制模式)。
0赞 Chris 7/23/2013
它似乎在没有第一行的情况下进行解析。让我确保能够以这种方式处理错误。对不起,花了这么长时间。每次我想测试时,我都必须重建整个 WiX 安装程序。
0赞 Chris 7/23/2013
@Richard - 它来自来自远程服务器的服务调用。
0赞 Jo Smo 5/8/2014
如果上述文件中有任何内容:请将其从文件中删除,然后重试。<?xml version="1.0" encoding="utf-8"?>

答:

16赞 Chris 7/23/2013 #1

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

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

这解决了我的问题。

评论

4赞 Ricardo Appleton 10/15/2013
有一次我收到这个错误,一开始结果是一个“?”。我只是用一个空白替换了它并让它运行......如果您正在阅读的文件的编码与预期的编码不同,也可能会发生这种情况
0赞 B. Clay Shannon-B. Crow Raven 9/5/2014
我试过了这个,但在.NETPrehistoric (1.1),我尝试使用“\r\n”来代替当时不可用的 Environment.NewLine。我得到,“指定的参数超出了有效值的范围。
0赞 Shesha 3/9/2016
@Chris:我已经尝试了你的解决方案。我得到了以下异常。System.ArgumentOutOfRangeException:StartIndex 不能小于零。参数
86赞 Ringo 3/14/2014 #2

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

评论

22赞 B. Clay Shannon-B. Crow Raven 9/5/2014
我正在使用 XDocument.Load(),并且遇到了问题。
1赞 CLS 1/24/2020
当 XmlDocument.Load() 因此在标头中指定时,它似乎会处理文件编码。如果没有,则可能需要处理 StreamReader 和 XmlDocument.LoadXml 以及其他工具。
176赞 Amit Merin 1/2/2015 #3

隐藏字符可能是 BOM。 问题的解释和解决方案可以在这里找到,归功于詹姆斯·舒伯特,基于詹姆斯·布兰金的答案 这里.

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

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赞 user1040975 5/7/2016
不确定,我想我必须继续寻找,但是当我这样做时,_byteOrderMarkUtf8 = “”。所以它没有抓住它。想法?
2赞 John Demetriou 10/24/2017
试过了,没有帮助。就此而言,XML 来自 DB
1赞 Mister Cook 4/29/2018
Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()) 的计算结果为空字符串
8赞 Polshgiant 7/27/2018
与上述评论者有相同的问题。使用对我来说是诀窍。归功于 Hans Passant:stackoverflow.com/a/19495964/38425xmlStartsWith(byteOrderMarkUtf8, StringComparison.Ordinal)
2赞 mknopf 4/11/2019
这为我解决了问题,非常感谢,我已经为此努力了一段时间。
12赞 pawciu 9/22/2015 #4

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

我在根级别对数据的解决方案无效。第 1 行,位置 1。in 将其替换为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 内容。

希望会有所帮助

4赞 MikeMajara 9/13/2017 #5

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

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

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

评论

1赞 Bravo 8/25/2022
谢谢迈克,这对我有用!
2赞 Mister Cook 4/29/2018 #6

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

        xml = new Regex("\\<\\?xml.*\\?>").Replace(xml, "");
0赞 Shubhasish Bhunia 8/14/2018 #7

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

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;
}

评论

0赞 hardyVeles 7/2/2019
这是一个解决方案,但很糟糕。这是编码问题,通过写入和读取文件,您实际上在不知不觉中执行了编码和解码,因为调用的 Load 方法的重载具有编码参数(System.Text.Encoding 编码)的默认值
0赞 Shubhasish Bhunia 7/4/2019
谢谢先生指出来,你能纠正我吗?
0赞 hardyVeles 7/11/2019
您应该使用 Encoding 类的方法对 String 进行解码和编码,根本不需要(和感觉)使用 File 方法或文件系统。请检查:learn.microsoft.com/en-us/dotnet/api/...
3赞 Michael Planer 8/17/2018 #8

我通过直接编辑字节数组解决了这个问题。 收集 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", "");

评论

0赞 ThanhLD 8/19/2019
它对我有用。但是在循环中,我们需要检查 byteArray.IndexOf(singleByte) != -1 或不删除它。
-1赞 Raj 2/7/2020 #9

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

2赞 tibbiustin 9/14/2020 #10

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

4赞 Nenad 10/19/2020 #11

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

使用将第二个构造函数参数设置为 true 的 created,将确定正确的编码和 create which 不会破坏方法。StreamReaderdetectEncodingFromByteOrderMarksstringXmlDocument.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`
}

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

public string GetXmlString(string url)
{
    byte[] bytes = GetResponseByteArray(url);
    return System.Text.Encoding.UTF8.GetString(bytes); // potentially exception on `LoadXml`
}
0赞 Meisam Rasouli 1/9/2023 #12

使用 XmlDataDocument 对象比使用 XDocument 或 XmlDocument 对象要好得多。XmlDataDocument 适用于 UTF8,并且对字节顺序序列没有问题。可以使用 ChildNodes 属性获取每个元素的子节点。 使用自定义函数,如下所示:

        static public void ReadXmlDataDocument2(string xmlFilePath)
    {
        
        if (xmlFilePath != null)
        {
            if (File.Exists(xmlFilePath))
            {
                System.IO.FileStream fs = default(System.IO.FileStream);
                try
                {
                    fs = new System.IO.FileStream(xmlFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                    System.Xml.XmlDataDocument k_XDoc = new System.Xml.XmlDataDocument();
                    k_XDoc.Load(fs);
                    fs.Close();
                    fs.Dispose();
                    fs = null;

                    XmlNodeList ndsRoot = k_XDoc.ChildNodes;
                    foreach (System.Xml.XmlNode xLog in ndsRoot)
                    {
                        foreach (System.Xml.XmlNode xLog2 in xLog.ChildNodes)
                        {
                            if (xLog2.Name == "ERRORs")
                            {
                                foreach (System.Xml.XmlNode xLog3 in xLog2.ChildNodes)
                                {
                                    if (xLog3.Name == "ErrorCode")
                                    {
                                        // Do something
                                    }
                                    if (xLog3.Name == "Description")
                                    {
                                        // Do something
                                    }
                                }
                            }
                        }
                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }