我有一个包含无效十六进制字符的XML。我已阅读this,this和this以及任何其他链接,但未能使其正常工作。
我使用XmlReader
- XmlDocument
,XDocument
和XmlTextReader
不是我的选择,因为有大于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 ++中的外观图像:
我如何创建xmlReader
对象只是这个简单的陈述:
using (xmlReader = XmlReader.Create(filePath, new XmlReaderSettings { CheckCharacters = false }))
答案 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
方法需要找出是否需要删除字符,进行删除,然后返回一个不同的值。代码会比较棘手 - 我希望你不需要它。