我查看了string escape into XML并发现它非常有用。
我想做类似的事情:转义要在XML-Attribute中使用的字符串。
该字符串可能包含\ r \ n。 XmlWriter类产生类似\ r \ n - >的东西。 &安培; #xD;&安培; #xA;
我目前使用的解决方案包括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类...
我的方法我目前正在使用这样的方法:
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
Bar"
EDIT2:
SecurityElement.Escape(unescaped);
也不起作用。
编辑3(最终):
使用Lars的所有非常有用的评论,我的最终实现如下:
注意:有效XMl不需要.Replace("\r", "
").Replace("\n", "
");
。这只是一种美容措施!
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", "
").Replace("\n", "
");
}
事实证明这是有效的XML,并且将由任何符合标准的XMl解析器进行解析:
<response message="Thank you,
LarsH!" />
答案 0 :(得分:7)
修改您引用的解决方案,
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", "
").Replace("\n", "
");
或
return node.InnerXml.Replace("\r", "
").Replace("\n", "
");
答案 1 :(得分: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 spec的属性值中是不正确的。
我的解决方案的灵感来自this post。
答案 2 :(得分:-1)
如果它可以提供任何帮助,使用多种语言,可以使用createCDATASection来避免所有XML特殊字符。
它增加了这样的东西:
<tag><![CDATA[ <somecontent/> ]]></tag>