在XML中存在无效的十六进制字符。

12 浏览
0 Comments

在XML中存在无效的十六进制字符。

我有一个包含无效十六进制字符的XML文件。我阅读了这个这个这个以及其他提供的链接,但都未能使其正常工作。

我正在使用XmlReader - XmlDocumentXDocumentXmlTextReader不是我的选择,因为XML文件的大小超过500GB,数量超过5亿。由于其“前向”方法以及不将所有XML细节加载到内存中,XMLReader是我最佳选择。也因为此原因,我无法重新创建或加载XML文件以替换无效字符。

以下是我正在使用的代码:

case XmlNodeType.Element:
if (xmlReader.Name.Equals("ROW"))
{
    DataRow dataRow = xmlDataTable.NewRow();
    XmlReader row = XmlReader.Create(xmlReader.ReadSubtree(), new XmlReaderSettings { CheckCharacters = false
                                                                            , ValidationType = ValidationType.None });
    // 迭代ROW内的元素
    // 这些是列项目
    if (row != null)
    {
        while (row.Read())
        {
            if (row.IsStartElement())
            {
                if (!row.Name.Equals("ROW"))
                {
                    string columnName = row.Name;
                    //row = XmlReader.Create(CleanInvalidXmlChars(row.ReadInnerXml()));
                    row.Read();
                    string value = CleanInvalidXmlChars(row.Value.ToString());
                    // 其他逻辑...

异常发生在row.Read();语句上。以下是我正在读取的示例XML文件:




    828  
    GJ102
                                       
                                       
    E
    815412
    0
    0
    0
    0
    A
    0



目前,我在使其正常工作方面遇到了困难。

编辑:

示例XML文件是导致我的代码出错的记录。我从记事本中将其复制并粘贴在这里,但它不显示无效字符。以下是在记事本中的外观图像:

enter image description here

我如何创建xmlReader对象只是这个简单的语句:

using (xmlReader = XmlReader.Create(filePath, new XmlReaderSettings { CheckCharacters = false }))

0
0 Comments

问题:在XML中出现无效的十六进制字符。

原因:不清楚为什么将CheckCharacters = false设置为false不能解决问题,更好的解决方法是一开始就以清洁的方式获取数据。但是,可以通过在TextReader中用替换字符替换每个无效字符来解决这个问题。

解决方法:

using System;
using System.IO;
using System.Xml;
class Test
{
    static void Main()
    {
        var text = "<foo>\0</foo>";
        var reader = XmlReader.Create(
             new XmlReplacingReader(new StringReader(text), ' '));
        while (reader.Read())
        {
            Console.WriteLine(reader.NodeType);
        }
    }
}
public sealed class XmlReplacingReader : TextReader
{
    private readonly TextReader original;
    private readonly char replacementChar;
    public XmlReplacingReader(TextReader original, char replacementChar)
    {
        this.original = original;
        this.replacementChar = replacementChar;
    }
    override public int Peek()
    {
        int ret = original.Peek();
        return MaybeReplace(ret);
    }
    override public int Read()
    {
        int ret = original.Read();
        return MaybeReplace(ret);
    }
    override public int Read(char[] buffer, int index, int count)
    {
        int ret = original.Read(buffer, index, count);
        for (int i = 0; i < ret; i++)
        {
            buffer[i + index] = MaybeReplace(buffer[i + index]);
        }
        return ret;
    }
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            original.Dispose();
        }
    }
    public override void Close()
    {
        original.Close();
    }
    private int MaybeReplace(int x)
    {
        return x < 0 ? x : MaybeReplace((char) x);
    }
    private char MaybeReplace(char c)
    {
        return (c >= ' ' || c == '\r' || c == '\n' || c == '\t') ? c : replacementChar;
    }
}

这依赖于你能够为文件创建一个TextReader,当然,如果你知道编码,可以使用File.OpenText来做到这一点。如果需要处理其他编码,可能需要一个更聪明的解决方案,但这应该能帮助你入门。

请注意,这种方法替换了无效字符。如果你想删除它们,这将变得更困难,而且可能效率更低,因为批量Read方法需要找出是否需要删除字符,执行删除操作,然后返回一个不同的值。代码将会更加复杂 - 希望你不需要它。

是的,我也在想为什么在这种情况下CheckCharacters不起作用。我已经在许多其他情况下测试过它,它的功能是正确的,但现在我甚至不知道我做错了什么。我已经看了你的代码片段一段时间了,将尝试实现它并更新任何信息。

0