我收到此错误。后来我搜索并发现了我的XML及其解决方案中非法字符的原因。但是我没有权限编辑这些文件。我的工作是读取和获取标签值,属性值和类似的东西。所以我无法使用&#01替换带有'\ x01'等转义符的二进制字符。我还尝试在XMLreader设置中包含CheckCharacters = false。它不需要这个。仍然是在抛出同样的错误。
是否无法修复XMLreader?我读到了关于XMLtextReader的内容。它可以跳过异常。但是我已经使用XMLreader编写了所有功能。如果我能为此找到解决方案,那将是件好事。否则我将不得不改变我的所有代码。
我的代码:
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
var filenames = System.IO.Directory
.EnumerateFiles(textBox1.Text, "*.xml", System.IO.SearchOption.AllDirectories)
.Select(System.IO.Path.GetFullPath);
foreach (var f in filenames)
{
var resolver = new XmlUrlOverrideResolver();
resolver.DtdFileMap[@"X1.DTD"] = @"\\location\X1.DTD";
resolver.DtdFileMap[@"R2.DTD"] = @"\\location\X2.DTD";
resolver.DtdFileMap[@"R5.DTD"] = @"\\location\R5.DTD";
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = resolver;
XmlReader doc = XmlReader.Create(f, settings);
while (doc.Read())
{
if ((doc.NodeType == XmlNodeType.Element) && (doc.Name == "ap"))
{
if (doc.HasAttributes)
{
String fin = doc.GetAttribute("ap");
if (fin == "no")
{
String[] array = new String[10000];
array[i] = (f);
File.AppendAllText(@"\\location\NAPP.txt", array[i] + Environment.NewLine);
i++;
}
else
{
String[] abs = new String[10000];
abs[i] = (f);
File.AppendAllText(@"\\location\APP.txt", abs[i] + Environment.NewLine);
i++;
}
}
}
}
}
MessageBox.Show("Done");
}
答案 0 :(得分:2)
这是一个非常简单的字符示例" filter"这将用空格重放0x06字符:
public class MyStreamReader : StreamReader {
public MyStreamReader(string path)
: base(path) {
}
public override int Read(char[] buffer, int index, int count) {
int res = base.Read(buffer, index, count);
for (int i = 0; i < res; i++) {
if (buffer[i] == 0x06) {
buffer[i] = ' ';
}
}
return res;
}
}
你这样使用它:
using (var sr = new MyStreamReader(f)) {
var doc = XmlReader.Create(sr, settings);
请注意,它非常简单,因为它将一个字符(0x06)替换为另一个字符(#34;长度&#34; (空间)。如果你想用&#34;序列替换一个字符&#34;角色(逃避它),它会变得更复杂(不是不可能,30分钟的工作困难)
(我已经检查过,似乎XmlTextReader
仅使用该方法,而不是Read()
方法)
与往常一样,当程序员告诉你30分钟时,它意味着0分钟或2小时: - )
这是更复杂的&#34; ReplacingStreamReader
:
/// <summary>
/// Only the Read methods are supported!
/// </summary>
public class ReplacingStreamReader : StreamReader
{
public ReplacingStreamReader(string path)
: base(path)
{
}
public Func<char, string> ReplaceWith { get; set; }
protected char[] RemainingChars { get; set; }
protected int RemainingCharsIndex { get; set; }
public override int Read()
{
int ch;
if (RemainingChars != null)
{
ch = RemainingChars[RemainingCharsIndex];
RemainingCharsIndex++;
if (RemainingCharsIndex == RemainingChars.Length)
{
RemainingCharsIndex = 0;
RemainingChars = null;
}
}
else
{
ch = base.Read();
if (ch != -1)
{
string replace = ReplaceWith((char)ch);
if (replace == null)
{
// Do nothing
}
else if (replace.Length == 1)
{
ch = replace[0];
}
else
{
ch = replace[0];
RemainingChars = replace.ToCharArray(1, replace.Length - 1);
RemainingCharsIndex = 0;
}
}
}
return ch;
}
public override int Read(char[] buffer, int index, int count)
{
int res = 0;
// We leave error handling to the StreamReader :-)
// We handle only "working" parameters
if (RemainingChars != null && buffer != null && index >= 0 && count > 0 && index + count <= buffer.Length)
{
int remainingCharsCount = RemainingChars.Length - RemainingCharsIndex;
res = Math.Min(remainingCharsCount, count);
Array.Copy(RemainingChars, RemainingCharsIndex, buffer, index, res);
RemainingCharsIndex += res;
if (RemainingCharsIndex == RemainingChars.Length)
{
RemainingCharsIndex = 0;
RemainingChars = null;
}
if (res == count)
{
return res;
}
index += res;
count -= res;
}
while (true)
{
List<char> sb = null;
int res2 = base.Read(buffer, index, count);
if (res2 == 0 || ReplaceWith == null)
{
return res;
}
int j = 0;
for (int i = 0; i < res2; i++)
{
char ch = buffer[index + i];
string replace = ReplaceWith(ch);
if (sb != null)
{
if (replace == null)
{
sb.Add(ch);
}
else
{
sb.AddRange(replace);
}
}
else if (replace == null)
{
buffer[j] = ch;
j++;
}
else if (replace.Length == 1)
{
buffer[j] = replace[0];
j++;
}
else if (replace.Length == 0)
{
// We do not advance
}
else
{
sb = new List<char>();
sb.AddRange(replace);
}
}
res2 = j;
if (sb != null)
{
int res3 = Math.Min(sb.Count, count - res2);
sb.CopyTo(0, buffer, index + res2, res3);
if (res3 < sb.Count)
{
RemainingChars = new char[sb.Count - res3];
RemainingCharsIndex = 0;
sb.CopyTo(res3, RemainingChars, 0, RemainingChars.Length);
}
res += res3;
}
else
{
res2 = j;
// Can't happen if sb != null (at least a character must
// have been added)
if (res2 == 0)
{
continue;
}
}
res += res2;
return res;
}
}
}
使用它像:
using (var sr = new ReplacingStreamReader(f))
{
sr.ReplaceWith = x =>
{
return x == 0x6 ? " " : null;
// return x == '.' ? " " : null; // Replace all . with
};
var doc = XmlReader.Create(sr, settings);
请注意ReplacingStreamReader
没有&#34;知道&#34;它正在修改的xml的哪一部分,所以很少有&#34; blind&#34;替换是好的:-)除了这个限制,你可以用任何字符串替换任何字符(null
表示{#1}}表示&#34;保留当前字符&#34;,相当于{{1在给出的示例中。返回ReplaceWith
有效,表示删除当前字符。)
该课程非常有趣:它为x.ToString()
提供了已读取的字符(并由string.Empty
过滤),但char[] RemainingChars
尚未返回方法,因为传递的缓冲区太小(ReplaceWith
方法可以&#34;放大&#34;读取字符串,使其对Read()
来说太大了!)。请注意,ReplaceWith
是buffer
而不是sb
。在代码方面,可能使用其中一个或几乎相同。
答案 1 :(得分:0)
您可以先将内容读入string
替换(转义)内容,然后将其加载到XmlReader
:
foreach (var f in filenames) {
string text;
using (StreamReader s = new StreamReader(f,Encoding.UTF8)) {
text = s.ReadToEnd();
}
text = text.Replace("\x01",@""); //replace the content
//load some settings
var resolver = new XmlUrlOverrideResolver();
resolver.DtdFileMap[@"X1.DTD"] = @"\\location\X1.DTD";
resolver.DtdFileMap[@"R2.DTD"] = @"\\location\X2.DTD";
resolver.DtdFileMap[@"R5.DTD"] = @"\\location\R5.DTD";
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = resolver;
XmlReader doc = XmlReader.Create(text, settings);
//perform processing task
//...
}