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

本文关键字:1行 位置 无效 数据 LoadData- xml | 更新日期: 2023-09-27 18:24:13

我试图在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,这样我就可以查看是否有任何错误。

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

隐藏的字符可能是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字符。

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

这里的问题是myString有那个标题行。第一行的开头可能有隐藏字符,或者是该行本身导致了错误。我把第一行剪成这样:

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

这解决了我的问题。

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

我的根级别的数据解决方案无效。第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字节[]。如果您需要使用字符串,您应该在字符串中查找"不可见"字节,并使用编码来调整xml内容以进行解析或加载。

希望它能帮助

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

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

在VS 2017中,您可以在Save按钮旁边的下拉列表中找到编码。

此错误的罪魁祸首是在将Streambyte[]数组转换为.NET string时确定编码的逻辑。

使用在第二构造函数参数detectEncodingFromByteOrderMarks设置为true的情况下创建的StreamReader,将确定正确的编码并创建不破坏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编码。下面的代码将生成在Visual Studio调试器中检查时看起来有效的string,或者将其复制粘贴到某个位置,但当与LoadLoadXml一起使用时,如果文件的编码与不带BOM的UTF8不同,则会生成异常。

public string GetXmlString(string url)
{
    byte[] bytes = GetResponseByteArray(url);
    return System.Text.Encoding.UTF8.GetString(bytes); // potentially exception on `LoadXml`
}

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

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

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

一开始我在逃离"&quot;字符,然后变音符号和特殊字母被显示为问号,最后出现了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等)。查看更多

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

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

使用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);
                }
            }
        }
    }

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