首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XmlTextWriter错误地写入控制字符

XmlTextWriter错误地写入控制字符
EN

Stack Overflow用户
提问于 2011-11-24 19:03:41
回答 3查看 13K关注 0票数 14

.NET的XmlTextWriter创建了无效的xml文件。

在XML中,允许使用一些控制字符,如“水平制表符”(	),但不允许使用其他控制字符,如“垂直制表符”()。(请参阅spec。)

我有一个字符串,其中包含XML中不允许的UTF-8控制字符。

尽管XmlTextWriter对字符进行了转义,但得到的结果仍然是无效的。

如何确保XmlTextWriter永远不会生成非法的XML文件?

或者,如果XmlTextWriter不能做到这一点,我如何从字符串中去掉XML中不允许的特定控制字符呢?

示例代码:

代码语言:javascript
复制
using (XmlTextWriter writer =
  new XmlTextWriter("test.xml", Encoding.UTF8))
{
  writer.WriteStartDocument();
  writer.WriteStartElement("Test");
  writer.WriteValue("hello \xb world");
  writer.WriteEndElement();
  writer.WriteEndDocument();
}

输出:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><Test>hello &#xB; world</Test>
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-11-24 19:55:17

该行为文档隐藏在documentation of the WriteString method中,但听起来像是适用于整个类。

使用Create创建的XmlWriter的默认行为是在尝试写入0x-0x1F范围内的字符值(不包括空白字符0x9、0xA和0xD)时引发ArgumentException。可以通过创建CheckCharacters属性设置为false的XmlWriter来写入这些无效的XML字符。这样做将导致字符被替换为数字字符实体(从&#0;&#0x1F)。此外,默认情况下,使用新运算符创建的XmlTextWriter将用数字字符实体替换无效字符。

因此,似乎是因为使用了XmlTextWriter类,所以最终写出了无效字符。对您来说,更好的解决方案是使用XmlWriter Class

票数 13
EN

Stack Overflow用户

发布于 2013-06-27 05:31:54

当我遇到同样的问题时,我发现了这个问题,最后我用正则表达式解决了这个问题:

代码语言:javascript
复制
return Regex.Replace(s, @"[\u0000-\u0008\u000B\u000C\u000E-\u001F]", "");

希望它能帮助某些人作为替代解决方案。

票数 3
EN

Stack Overflow用户

发布于 2011-11-25 05:37:39

SecurityElement.Escape等内置的.NET转义程序也不能正确地转义/剥离它。

  • 如果您的应用程序是唯一与文件交互的应用程序,则可以在编写器和读取器上将CheckCharacters设置为false。但是,从技术上讲,生成的XML文件仍然是无效的

请参见:

代码语言:javascript
复制
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提到这些字符是不鼓励的,但仍然是有效的。

代码语言:javascript
复制
public static class XmlTextExtentions
{
    private static readonly Dictionary<char, string> textEntities = new Dictionary<char, string> {
        { '&', "&amp;"}, { '<', "&lt;" }, { '>', "&gt;" }, 
        { '"', "&quot;" }, { '\'', "&apos;" }
    };
    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、维基百科和规范标记为有效(尽管不鼓励)字符的测试。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8256010

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档