10

我查看了字符串转义到 XML并发现它非常有用。

我想做类似的事情:转义要在 XML 属性中使用的字符串。

该字符串可能包含 \r\n。XmlWriter 类产生类似 \r\n ->

我目前使用的解决方案包括 XmlWriter 和 StringBuilder,而且相当难看。

有什么提示吗?

Edit1:
很抱歉让 LarsH 失望,买我的第一个方法是

public static string XmlEscapeAttribute(string unescaped)
{
    XmlDocument doc = new XmlDocument();
    XmlAttribute attr= doc.CreateAttribute("attr");
    attr.InnerText = unescaped;
    return attr.InnerXml;
}

这没用。XmlEscapeAttribute("Foo\r\nBar")将导致"Foo\r\nBar"

我使用 .NET Reflector 来了解 XmlTextWriter 如何转义属性。它使用内部的 XmlTextEncoder 类...

我的方法我目前正在使用这样的 lokks:

public static string XmlEscapeAttribute(string unescaped)
{
    if (String.IsNullOrEmpty(unescaped)) return unescaped;

    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    StringBuilder sb = new StringBuilder();
    XmlWriter writer = XmlWriter.Create(sb, settings);

    writer.WriteStartElement("a");
    writer.WriteAttributeString("a", unescaped);
    writer.WriteEndElement();
    writer.Flush();
    sb.Length -= "\" />".Length;
    sb.Remove(0, "<a a=\"".Length);

    return sb.ToString();
}

它很丑而且可能很慢,但它确实有效:XmlEscapeAttribute("Foo\r\nBar")会导致"Foo&#xD;&#xA;Bar"

编辑2:

SecurityElement.Escape(unescaped);

也不起作用。

编辑3(最终):

使用来自 Lars 的所有非常有用的评论,我的最终实现如下所示:

注意.Replace("\r", "&#xD;").Replace("\n", "&#xA;");有效 XMl 不需要。这只是一种美容措施!

    public static string XmlEscapeAttribute(string unescaped)
    {

        XmlDocument doc = new XmlDocument();
        XmlAttribute attr= doc.CreateAttribute("attr");
        attr.InnerText = unescaped;
        // The Replace is *not* required!
        return attr.InnerXml.Replace("\r", "&#xD;").Replace("\n", "&#xA;");
    }

事实证明这是有效的 XML,将被任何符合标准的 XMl 解析器解析:

<response message="Thank you,
LarsH!" />
4

3 回答 3

9

修改你引用的解决方案,怎么样

public static string XmlEscape(string unescaped)
{
    XmlDocument doc = new XmlDocument();
    var node = doc.CreateAttribute("foo");
    node.InnerText = unescaped;
    return node.InnerXml;
}

我所做的只是将 CreateElement() 更改为 CreateAttribute()。属性节点类型确实具有 InnerText 和 InnerXml 属性。

我没有测试这个的环境,但我很想知道它是否有效。

更新:或更简单地说,按照您链接到的问题的另一个答案中的建议使用SecurityElement.Escape() 。这将转义引号,因此适合用于属性文本。

更新 2:请注意,回车和换行不需要在属性值中进行转义,以使 XML 格式正确。如果您希望它们因其他原因被转义,您可以使用 String.replace() 来实现,例如

SecurityElement.Escape(unescaped).Replace("\r", "&#xD;").Replace("\n", "&#xA;");

或者

return node.InnerXml.Replace("\r", "&#xD;").Replace("\n", "&#xA;");
于 2010-12-16T18:53:09.683 回答
0
public static string XmlEscapeAttribute(string unescaped)
{
    if (string.IsNullOrEmpty(unescaped))
        return unescaped;

    var attributeString = new XAttribute("n", unescaped).ToString();

    // Extract the string from the text like: n="text".
    return attributeString.Substring(3, attributeString.Length - 4);
}

此解决方案类似于@Mathias E. 提出的解决方案,但它使用 LINQ to XML 而不是 XmlDocument,因此应该更快。

SecurityElement.Escape()解决方案有几个问题。首先,它不会对新行进行编码,因此必须作为附加步骤来完成。此外,它根据XML 规范将撇号编码为&apos;属性值中不正确的撇号。

我的解决方案的灵感来自这篇文章

于 2020-03-03T19:25:15.970 回答
-3

如果它可以有任何帮助,在几种语言中,使用 createCDATASection 来避免所有 XML 特殊字符。

它增加了这样的东西:

<tag><![CDATA[ <somecontent/> ]]></tag>
于 2010-12-16T19:04:32.480 回答