XML中的十六进制字符无效

时间:2015-10-09 09:39:39

标签: c# xml

我有一个包含无效十六进制字符的XML。我已阅读thisthisthis以及任何其他链接,但未能使其正常工作。

我使用XmlReader - XmlDocumentXDocumentXmlTextReader不是我的选择,因为有大于500GB的XML文件和5亿数量。 XMLReader是我的最佳选择,因为它的"转发"方法,而不是将所有XML细节加载到内存中。另外,正因为如此,我无法重新创建或加载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 });

    // iterate on elements inside ROW
    // these are the column items
    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());

                    // all other logics ...

异常引发row.Read();语句。这是我正在阅读的示例XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<MFAINSBRP>
<ROW>
    <INSTITUTION_CODE>828  </INSTITUTION_CODE>
    <BRANCH_CODE>GJ102</BRANCH_CODE>
    <BRANCH_NAME>                                   </BRANCH_NAME>
    <BRANCH_NAME_FRENCH>                                   </BRANCH_NAME_FRENCH>
    <LANGUAGE_CODE>E</LANGUAGE_CODE>
    <ADDR_NO>815412</ADDR_NO>
    <FAX_AREA>0</FAX_AREA>
    <FAX_PHONE>0</FAX_PHONE>
    <AREA_CODE>0</AREA_CODE>
    <PHONE_NO>0</PHONE_NO>
    <STATUS>A</STATUS>
    <PHONE_EXT>0</PHONE_EXT>
</ROW>
<!--ALL OTHER RECORDS-->
</MFAINSBRP>

现在,我一直坚持做这项工作。

修改

示例XML文件是使我的代码中断的记录。我从Notepad ++复制粘贴它,但它没有显示无效字符。以下是Notepad ++中的外观图像:

enter image description here

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

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

1 个答案:

答案 0 :(得分:1)

我不清楚为什么CheckCharacters = false没有为您解决问题,而且我已经提到远远更好的修复方法是以干净的方式获取数据。

但是,您可以通过使用TextReader使用的XmlReader中的替换替换每个无效字符来解决此问题。这是一个简短而完整的例子:

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方法需要找出是否需要删除字符,进行删除,然后返回一个不同的值。代码会比较棘手 - 我希望你不需要它。