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

问题描述 投票:0回答: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,以便查看是否有任何错误。

c# xml xml-parsing wix
13个回答
180
投票

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


91
投票

改用

Load()
方法,就能解决问题。 查看更多


16
投票

这里的问题是

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

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

这解决了我的问题。


12
投票

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

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

希望对你有帮助


4
投票

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

文件 > 文件另存为... > 另存为 UTF-8 且无签名。

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


4
投票

此错误的罪魁祸首是确定将

Stream
byte[]
数组转换为 .NET
string
时的编码的逻辑。

使用将第二个构造函数参数

StreamReader
设置为 true 创建的
detectEncodingFromByteOrderMarks
,将确定正确的编码并创建不会破坏
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`
}

常见的错误是盲目地在

UTF8
stream
上使用
byte[]
编码。下面的代码将生成
string
,在 Visual Studio 调试器中检查或复制粘贴到某处时看起来有效,但如果文件编码与不带 BOM 的 UTF8 不同,则与
Load
LoadXml
一起使用时会产生异常。

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

3
投票

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

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", "");

2
投票

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

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

2
投票

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

我查看了答案,并使用@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 等)。 查看更多


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

0
投票

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

0
投票

简单地说:

if (myString[0] == '\ufeff') myString = myString.Substring(1);

-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.