【问题标题】:Azure Web App XML Data at the root level is invalid. Line 1, position 1根级别的 Azure Web App XML 数据无效。第 1 行,位置 1
【发布时间】:2019-07-15 18:41:51
【问题描述】:

给定两个 XML 文件,其内容开头如下:

文件 A

<?xml

文件 B

<?xml

文件 B 会出错。所以我们实现了以下代码来移除在生产环境中工作多年的 BOM:

private static string RemoveUTF8ByteOrderMark(string str)
{
    var byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());

    if (str.StartsWith(byteOrderMarkUtf8))
    {    
        str = str.Remove(0, byteOrderMarkUtf8.Length);
    }

    return str;
}

删除 BOM 后,我们使用以下方法将字符串解析为 XML:

public static XDocument ParseXmlDocumentFromText(string fileText)
{
    if (string.IsNullOrEmpty(fileText)) return null;

    var nsm = new XmlNamespaceManager(new NameTable());

    nsm.AddNamespace("*****", "*****");

    var ctx = new XmlParserContext(null, nsm, null, XmlSpace.Default);
    var settings = new XmlReaderSettings { ProhibitDtd = false, XmlResolver = null };

    using (var fs = new StringReader(fileText))
    {
        using (var reader = XmlReader.Create(fs, settings, ctx))
        {
            var doc = new XmlDocument();

            doc.Load(reader);

            return XDocument.Parse(doc.OuterXml);
        }
    }
}

现在,我们已将我们的网站从专用服务器迁移到 Azure Web 应用程序,在文件 B 继续正确加载的同时,文件 A 出现错误 doc.Load(reader);

System.Web.HttpUnhandledException (0x80004005): 类型异常 'System.Web.HttpUnhandledException' 被抛出。 ---> System.Xml.XmlException:根级别的数据无效。 1号线, 位置 1。

在 Azure 中,如果我禁用 RemoveUTF8ByteOrderMark(...) 调用,则文件 A 会正确加载,而文件 B 会出错(如预期的那样)。

当我在我的计算机上进行本地测试时,两个文件都在启用RemoveUTF8ByteOrderMark(...) 的情况下加载,这与我们旧的专用服务器一致。在所有 3 个环境中,XML 文件都是从 Azure blob 存储中提取的,因此始终使用完全相同的文件。

Azure Web App 中发生了什么改变了此代码的运行方式?

更新

在 Azure 中,当调用RemoveUTF8ByteOrderMark(...) 时,我可以看到返回的文本如下:

文件 A

?xml 

文件 B

<?xml 

那么为什么RemoveUTF8ByteOrderMark(...) 显然会导致领先的&lt; 被剥离?

【问题讨论】:

    标签: c# asp.net encoding azure-web-app-service


    【解决方案1】:

    您的代码似乎在处理使用 UTF-8 编码的文件时没有问题。但是根据wiki页面Byte order mark,不同编码的文件中BOM头的字节长度是不同的,如下图。

    所以一个通用的去除文件BOM头的解决方案,你需要先检测文件编码,然后去除文件头的不同长度字节才能得到真正的没有BOM的内容。

    在 C# 和 C++ 中有一个 GitHub repo AutoItConsulting/text-encoding-detect 来帮助检测文本内容编码和检查 BOM,如下面的the code

    /// <summary>
    ///     Gets the BOM length for a given Encoding mode.
    /// </summary>
    /// <param name="encoding"></param>
    /// <returns>The BOM length.</returns>
    public static int GetBomLengthFromEncodingMode(Encoding encoding)
    {
        int length;
    
        switch (encoding)
        {
            case Encoding.Utf16BeBom:
            case Encoding.Utf16LeBom:
                length = 2;
                break;
    
            case Encoding.Utf8Bom:
                length = 3;
                break;
    
            default:
                length = 0;
                break;
        }
    
        return length;
    }
    
    /// <summary>
    ///     Checks for a BOM sequence in a byte buffer.
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="size"></param>
    /// <returns>Encoding type or Encoding.None if no BOM.</returns>
    public Encoding CheckBom(byte[] buffer, int size)
    {
        // Check for BOM
        if (size >= 2 && buffer[0] == _utf16LeBom[0] && buffer[1] == _utf16LeBom[1])
        {
            return Encoding.Utf16LeBom;
        }
    
        if (size >= 2 && buffer[0] == _utf16BeBom[0] && buffer[1] == _utf16BeBom[1])
        {
            return Encoding.Utf16BeBom;
        }
    
        if (size >= 3 && buffer[0] == _utf8Bom[0] && buffer[1] == _utf8Bom[1] && buffer[2] == _utf8Bom[2])
        {
            return Encoding.Utf8Bom;
        }
    
        return Encoding.None;
    }
    

    我认为您可以直接使用或更改这些代码来解决您的问题,以删除文件中可能存在的 BOM 字节。

    同时,如果你只需要处理XML文件的内容,我认为一个简单的方法是IndexOf&lt;?xml对于一个可能有BOM字节的字符串,因为&lt;?xml字符串是一个固定的内容在XML DTD。

    这是我的示例代码,它适用于我的 xml 文件,无论是否包含 BOM 字节。

    int index = str.IndexOf("<?xml");
    return str.Substring(index);
    

    希望对你有帮助。

    【讨论】:

    • 完美运行,谢谢。如果您共享的 CheckBom(...) 方法返回“Encoding.None”,我将退出我的 RemoveUTF8ByteOrderMark(...) 方法。
    猜你喜欢
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 2020-12-19
    • 2011-10-28
    • 2018-03-30
    • 2013-07-21
    • 1970-01-01
    相关资源
    最近更新 更多