以下解决方案可以删除任何无效的XML字符,但是我认为它的性能非常好,并且特别是在字符串没有任何无效字符的情况下,它不会分配新的StringBuilder和新字符串,直到已确定字符串中有任何无效字符。 因此,热点最终只是在字符上的单个for循环,检查最终通常不超过每个char上的两个大于/小于数字比较。 如果找不到,则只返回原始字符串。 当绝大多数字符串都很好时,这非常有帮助,它很快地将其作为输入和输出(没有浪费的分配等)。
- 更新 -
请参见下面如何直接编写具有这些无效字符的XElement,尽管它使用了此代码 -
其中部分代码受到Mr. Tom Bogle的解决方案的影响。 还请参见同一线程上superlogical的帖子中的有用信息。 然而,所有这些都总是实例化新的StringBuilder和string。
用法:
string xmlStrBack = XML.ToValidXmlCharactersString("any string")
测试:
public static void TestXmlCleanser()
{
string badString = "My name is Inigo Montoya";
string goodString = "My name is Inigo Montoya!";
string back1 = XML.ToValidXmlCharactersString(badString);
string back2 = XML.ToValidXmlCharactersString(goodString);
XElement x1 = new XElement("test", back1);
XElement x2 = new XElement("test", back2);
XElement x3WithBadString = new XElement("test", badString);
string xml1 = x1.ToString();
string xml2 = x2.ToString().Print();
string xmlShouldFail = x3WithBadString.ToString();
}
// --- 代码 --- (我有这些方法在一个名为XML的静态实用类中)
public static string ToValidXmlCharactersString(string s, int startIndex = 0)
{
int firstInvalidChar = IndexOfFirstInvalidXMLChar(s, startIndex);
if (firstInvalidChar < 0)
return s;
startIndex = firstInvalidChar;
int len = s.Length;
var sb = new StringBuilder(len);
if (startIndex > 0)
sb.Append(s, 0, startIndex);
for (int i = startIndex; i < len; i++)
if (IsLegalXmlChar(s[i]))
sb.Append(s[i]);
return sb.ToString();
}
public static int IndexOfFirstInvalidXMLChar(string s, int startIndex = 0)
{
if (s != null && s.Length > 0 && startIndex < s.Length) {
if (startIndex < 0) startIndex = 0;
int len = s.Length;
for (int i = startIndex; i < len; i++)
if (!IsLegalXmlChar(s[i]))
return i;
}
return -1;
}
public static bool IsLegalXmlChar(char c)
{
if (c > 31 && c <= 55295)
return true;
if (c < 32)
return c == 9 || c == 10 || c == 13;
return (c >= 57344 && c <= 65533) || c > 65535;
}
======== ======== ========
直接使用XElement.ToString
======== ======== ========
首先,这是一个扩展方法的用法:
string result = xelem.ToStringIgnoreInvalidChars();
-- Fuller测试 --
public static void TestXmlCleanser()
--- 代码 ---
public static string ToStringIgnoreInvalidChars(this XElement xml, bool deleteInvalidChars = true, bool indent = true, char? indentChar = null)
return swriter.ToString();
}
-- 这里使用以下的 XmlTextWriter --
public class XmlTextWriterIgnoreInvalidChars : XmlTextWriter
{
public bool DeleteInvalidChars { get; set; }
public XmlTextWriterIgnoreInvalidChars(TextWriter w, bool deleteInvalidChars = true) : base(w)
{
DeleteInvalidChars = deleteInvalidChars;
}
public override void WriteString(string text)
{
if (text != null && DeleteInvalidChars)
text = XML.ToValidXmlCharactersString(text);
base.WriteString(text);
}
}
<
这样只需要转义的字符。 - Michael Kay