.NET的XmlTextWriter创建了无效的xml文件。
在XML中,允许使用一些控制字符,如“水平制表符”(	),但不允许使用其他控制字符,如“垂直制表符”()。(请参阅spec。)
我有一个字符串,其中包含XML中不允许的UTF-8控制字符。
尽管XmlTextWriter对字符进行了转义,但得到的结果仍然是无效的。
如何确保XmlTextWriter永远不会生成非法的XML文件?
或者,如果XmlTextWriter不能做到这一点,我如何从字符串中去掉XML中不允许的特定控制字符呢?
示例代码:
using (XmlTextWriter writer =
new XmlTextWriter("test.xml", Encoding.UTF8))
{
writer.WriteStartDocument();
writer.WriteStartElement("Test");
writer.WriteValue("hello \xb world");
writer.WriteEndElement();
writer.WriteEndDocument();
}输出:
<?xml version="1.0" encoding="utf-8"?><Test>hello  world</Test>发布于 2011-11-24 19:55:17
该行为文档隐藏在documentation of the WriteString method中,但听起来像是适用于整个类。
使用Create创建的XmlWriter的默认行为是在尝试写入0x-0x1F范围内的字符值(不包括空白字符0x9、0xA和0xD)时引发ArgumentException。可以通过创建CheckCharacters属性设置为false的XmlWriter来写入这些无效的XML字符。这样做将导致字符被替换为数字字符实体(从
�到�x1F)。此外,默认情况下,使用新运算符创建的XmlTextWriter将用数字字符实体替换无效字符。
因此,似乎是因为使用了XmlTextWriter类,所以最终写出了无效字符。对您来说,更好的解决方案是使用XmlWriter Class。
发布于 2013-06-27 05:31:54
当我遇到同样的问题时,我发现了这个问题,最后我用正则表达式解决了这个问题:
return Regex.Replace(s, @"[\u0000-\u0008\u000B\u000C\u000E-\u001F]", "");希望它能帮助某些人作为替代解决方案。
发布于 2011-11-25 05:37:39
SecurityElement.Escape等内置的.NET转义程序也不能正确地转义/剥离它。
CheckCharacters设置为false。但是,从技术上讲,生成的XML文件仍然是无效的。请参见:
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.CheckCharacters = false;
var sb = new StringBuilder();
var w = XmlWriter.Create(sb, xmlWriterSettings);
w.WriteStartDocument();
w.WriteStartElement("Test");
w.WriteString("hello \xb world");
w.WriteEndElement();
w.WriteEndDocument();
w.Close();
var xml = sb.ToString();CheckCharacters设置为true(默认情况下)有点太严格,因为它只会抛出一个异常。对无效的XML字符更宽松的另一种方法是剥离它们:谷歌一下就得到了白名单XmlTextEncoder,但是它也会删除DEL和其他在U+007F-U+0084,U+0086-U+009F范围内的字符,根据维基百科上的Valid XML Characters,这些字符只在特定的上下文中有效,RFC提到这些字符是不鼓励的,但仍然是有效的。
public static class XmlTextExtentions
{
private static readonly Dictionary<char, string> textEntities = new Dictionary<char, string> {
{ '&', "&"}, { '<', "<" }, { '>', ">" },
{ '"', """ }, { '\'', "'" }
};
public static string ToValidXmlString(this string str)
{
var stripped = str
.Select((c,i) => new
{
c1 = c,
c2 = i + 1 < str.Length ? str[i+1]: default(char),
v = XmlConvert.IsXmlChar(c),
p = i + 1 < str.Length ? XmlConvert.IsXmlSurrogatePair(str[i + 1], c) : false,
pp = i > 0 ? XmlConvert.IsXmlSurrogatePair(c, str[i - 1]) : false
})
.Aggregate("", (s, c) => {
if (c.pp)
return s;
if (textEntities.ContainsKey(c.c1))
s += textEntities[c.c1];
else if (c.v)
s += c.c1.ToString();
else if (c.p)
s += c.c1.ToString() + c.c2.ToString();
return s;
});
return stripped;
}
}这通过了所有的XmlTextEncoder测试,除了期望它剥离DEL XmlConvert.IsXmlChar、维基百科和规范标记为有效(尽管不鼓励)字符的测试。
https://stackoverflow.com/questions/8256010
复制相似问题