创建XML
时出错Msg 6841,Level 16,State 1,Line 26 FOR XML无法序列化 节点'value'的数据,因为它包含一个字符(0x000C) XML中不允许使用。要使用FOR XML检索此数据,请将其转换 到二进制,varbinary或图像数据类型并使用BINARY BASE64 指令。
弄清楚如何使用TSQL解决这个问题
我的问题是如何防止它
此数据通过.NET C#加载
已经做了一些清理工作如下:
- 删除前导和尾随空格
- 将多个空格连接到单个空格
什么字符会破坏FOR XML?
如何在.NET C#中识别和删除这些字符? 在输入数据之前甚至进入SQL。
XML是使用TSQL FOR XML(不是通过.NET)生成的。
找到此链接 Valid characters in XML
以下代码点范围中的Unicode代码点始终是 在XML 1.1文档中有效:[2] U + 0001-U + D7FF,U + E000-U + FFFD:这个 包括大多数C0和C1控制字符,但不包括一些(不是 所有)BMP中的非字符(代理,U + FFFE和U + FFFF都是 禁止的); U + 10000-U + 10FFFF:这包括所有代码点 补充飞机,包括非人物。
我不知道如何测试U + 0001-U + D7FF。
答案不仅仅是问题 正如问题所述,我已经在进行其他输入过滤 我只想添加xml 在实际应用程序中将过滤掉所有控制字符,因为此用户数据不应具有任何控制字符 win1252部分是与存储在SQL char(byte)中的数据对齐。
在1.1中允许使用1.0字符集,因为我的FOR XML是允许的 也只适用于Int16,因为char是Int16 in .NET。
public static string RemoveDiatricsXMLsafe(string unicodeString, bool toLower, bool toWin1252)
{
// cleary could just create the Regex and validXMLsingle once in the ctor
unicodeString = Regex.Replace(unicodeString, @"\s{2,}", " ");
//U+0009, U+000A, U+000D: these are the only C0 controls accepted in XML 1.0;
//U+0020–U+D7FF, U+E000–U+FFFD
Int16[] validXMLsingle = new Int16[4];
validXMLsingle[0] = Int16.Parse("0020", System.Globalization.NumberStyles.HexNumber);
validXMLsingle[1] = Int16.Parse("0009", System.Globalization.NumberStyles.HexNumber);
validXMLsingle[2] = Int16.Parse("000A", System.Globalization.NumberStyles.HexNumber);
validXMLsingle[3] = Int16.Parse("000D", System.Globalization.NumberStyles.HexNumber);
unicodeString = unicodeString.Trim();
Int16 u16;
StringBuilder sb = new StringBuilder();
bool validXML = false;
if (toLower) unicodeString = unicodeString.ToLowerInvariant();
foreach (char c in unicodeString.Normalize(NormalizationForm.FormD)) // : NormalizationForm.FormKD) breaks
{
switch (CharUnicodeInfo.GetUnicodeCategory(c))
{
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.EnclosingMark:
//do nothing
break;
default:
u16 = (Int16)c;
validXML = false;
if (u16 >= validXMLsingle[0]) validXML = true;
else if (u16 == validXMLsingle[1]) validXML = true;
else if (u16 == validXMLsingle[2]) validXML = true;
else if (u16 == validXMLsingle[3]) validXML = true;
if (validXML) sb.Append(c);
break;
}
}
if (!toWin1252)
{
return sb.ToString();
}
else
{
Encoding win1252 = Encoding.GetEncoding("Windows-1252");
Encoding unicode = Encoding.Unicode;
// Convert the string into a byte array.
byte[] unicodeBytes = unicode.GetBytes(sb.ToString());
// Perform the conversion from one encoding to the other.
byte[] win1252Bytes = Encoding.Convert(unicode, win1252, unicodeBytes);
// Convert the new byte[] into a char[] and then into a string.
char[] win1252Chars = new char[win1252.GetCharCount(win1252Bytes, 0, win1252Bytes.Length)];
win1252.GetChars(win1252Bytes, 0, win1252Bytes.Length, win1252Chars, 0);
return new string(win1252Chars);
//string win1252String = new string(win1252Chars);
//return win1252String;
}
}
答案 0 :(得分:1)
我猜是'0x000C' = '<'
(http://www.wimpyplayer.com/docs/howto/special_characters.html)。那么,在插入之前,您是否只需要将XML放入每个节点中的数据?
在此处回答:String escape into XML
public static string XmlEscape(string unescaped)
{
XmlDocument doc = new XmlDocument();
var node = doc.CreateElement("root");
node.InnerText = unescaped;
return node.InnerXml;
}
public static string XmlUnescape(string escaped)
{
XmlDocument doc = new XmlDocument();
var node = doc.CreateElement("root");
node.InnerXml = escaped;
return node.InnerText;
}
答案 1 :(得分:1)
在.Net方面,您应该能够使用正则表达式来判断您是否有一只奇怪的鸟:
var reg = new Regex("[^[\u0001-\ud7ff\ue000-\ufffd)]");
if(reg.IsMatch(...)
{
// do what you want if you find something you don't want
}