使用来自网络的编码 ISO-8859-1 解析 XML

Posted

技术标签:

【中文标题】使用来自网络的编码 ISO-8859-1 解析 XML【英文标题】:Parse XML with the encoding ISO-8859-1 from the web 【发布时间】:2015-05-12 23:50:53 【问题描述】:

我需要从 Web 读取一个编码为 ISO-8859-1 的 XML 文件。用它创建一个 XmlDocument 后,我​​尝试将它的一些 InnerText 转换为 UTF。但这没有用。然后我尝试更改 HttpClient 上的编码。响应字符串的格式正确,但在创建 XmlDocument 时,应用程序崩溃并出现异常:HRESULT: 0xC00CE55F 或 XML 字符串上出现非预期字符。我该如何解决这个问题?

代码片段:

private static async Task<string> GetResultsAsync(string uri)
        
            var client = new HttpClient();
            var response = await client.GetByteArrayAsync(uri);
            var responseString = Encoding.GetEncoding("iso-8859-1").GetString(response, 0, response.Length - 1);
            return responseString;
        

public static async Task GetPodcasts(string url)
        
            var progrmas = await GetGroupAsync("prog");
            HttpClient client = new HttpClient();

            //Task<string> pedido = client.GetStringAsync(url);
            //string res = await pedido; //Gets the string with the wrong chars, LoadXml doesn't fails

            res = await GetResultsAsync(url); //Gets the string properly formatted
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(res);  //Crashes here
            XmlElement root = doc.DocumentElement;

            XmlNodeList nodes = root.SelectNodes("//item");

            //Title
            var node_titles = root.SelectNodes("//item/title");
            IEnumerable<string> query_titles = from nodess in node_titles select nodess.InnerText;
            List<string> list_titles = query_titles.ToList();
            //........

            for (int i = 0; i < list_titles.Count; i++)
            
                PodcastItem podcast = new PodcastItem();
                string title = list_titles[i];


                //First attempt to convert a field from the XmlDocument, with the wrong chars. Only replaces the bad encoding with a '?':

                //Encoding iso = Encoding.GetEncoding("ISO-8859-1");
                //Encoding utf8 = Encoding.UTF8;
                //byte[] utfBytes = utf8.GetBytes(title);
                //byte[] isoBytes = Encoding.Convert(utf8, iso, utfBytes);
                //string msg = iso.GetString(isoBytes, 0, isoBytes.Length - 1);

                PodcastItem dataItem = new PodcastItem(title + pubdate, title, link, description, "", pubdate);
                progrmas.Items.Add(dataItem);
            

        

【问题讨论】:

什么是title?真的不清楚你想做什么。还要注意XmlDocumentXDocument 是不同的类。如果您已经将文档转换为 string,可能为时已晚 - 您应该将其以原始 binary 表示形式(例如作为流)提供,并让 XML 解析器处理解码。 我已经更正了你提到的问题。 您是否尝试过将二进制数据提供给 XmlDocument? XML 文件 advertise 是否采用 ISO-8859-1 编码? (该文档是否可以公开访问,以便我们自己寻找?)一个简短但完整的程序来证明这个问题真的很有帮助。 当前代码与文档的 url:pastebin.com/sPbxTShC 这不是一个简短但完整的程序,您应该将其包含在问题中 【参考方案1】:

我不确定您为什么要尝试对自己进行编码,但它在您身上崩溃如此严重的原因可能是因为您忘记获取数组的最后一个字节。这段代码对我有用:

    static async Task<string> LoadDecoced()
    
        var client = new HttpClient();
        var response = await client.GetByteArrayAsync("http://www.rtp.pt/play/podcast/469");
        var responseString = Encoding
           .GetEncoding("iso-8859-1")
           .GetString(response, 0, response.Length); // no -1 here, we want all bytes!
        return responseString;
    

如果我让 HttpClient 弄清楚你的代码对我有用:

    static async Task<string> Load()
    
        var hc = new HttpClient();
        string s = await hc.GetStringAsync("http://www.rtp.pt/play/podcast/469");
        return s;
    

    static void Main(string[] args)
    

        var xd = new XmlDocument();
        string res = Load().Result;
        xd.LoadXml(res);
        var node_titles = xd.DocumentElement.SelectNodes("//item/title");

        Console.WriteLine(node_titles.Count);
    

如果您使用的是非移动设备/非 WinRT,XmlDocument.Load 接受流也是如此:

    static async Task<Stream> LoadStream()
    
        var hc = new HttpClient();
        var stream = await hc.GetStreamAsync("http://www.rtp.pt/play/podcast/469");
        return stream;
    

    static void Main(string[] args)
    

        var xd2 = new XmlDocument();
        xd2.Load(LoadStream().Result);

        var node_titles2 = xd2.DocumentElement.SelectNodes("//item/title");

        Console.WriteLine(node_titles2.Count);
    

这是我控制台中的结果:

你确定你没有在其他地方编码吗?

作为一般建议:框架类能够处理最常见的编码场景。尝试让它工作,而不必摆弄 Encoding 类。

【讨论】:

在你的答案的第一个代码中,一个类似的字符:�被替换为'?'而不是正确的。带有 Stream 的那个似乎工作正常。但由于某种原因,我只对来自该提供商的提要有问题,我刚刚检查过,我可以毫无问题地阅读这个 feeds.tsf.pt/TsfFitness。 @celsoap7 它在哪里做的?我添加了标题的控制台输出的屏幕截图,据我所知,似乎没有一个是错误编码的? 我的使用展位方法:i.imgur.com/0hkI5hy.png 你可以看到差异。不幸的是,WinRT 和 Windows Phone 没有 Load 方法,只有 LoadXML 你应该得到你的字符串的整个数组,而不是少一个,看我的更新

以上是关于使用来自网络的编码 ISO-8859-1 解析 XML的主要内容,如果未能解决你的问题,请参考以下文章

iso-8859-1 是啥编码

使用 .NET 如何将包含 Latin-1 重音字符的 ISO 8859-1 编码文本文件转换为 UTF-8

乱码问题

XML 解析 - PHP 编码

在 Jboss 上使用 ISO-8859-1 编码和 JSF 2

使用 NSString 将 UTF-8 编码转换为 ISO 8859-1 编码