Các giải pháp trên không hiệu quả đối với tôi nếu mã hex có trong xml. ví dụ.
<element></element>
Đoạn mã dưới đây sẽ phá vỡ:
string xmlFormat = "<element>{0}</element>";
string invalid = " ";
string xml = string.Format(xmlFormat, invalid);
xml = Regex.Replace(xml, @"[\x01-\x08\x0B\x0C\x0E\x0F\u0000-\u0008\u000B\u000C\u000E-\u001F]", "");
XDocument.Parse(xml);
Nó trả về:
XmlException: '', thập lục phân giá trị 0x08, là một nhân vật không hợp lệ. Dòng 1, vị trí 14.
Sau đây là regex được cải thiện và khắc phục vấn đề nêu trên:
& #x ([0-8BCEFbcef] | 1 [0-9A-Pháp-f]); | [\ x01- \ x08 \ x0B \ x0C \ x0E \ x0F \ u0000- \ u0008 \ u000B \ u000C \ u000E- \ u001F]
Dưới đây là một thử nghiệm đơn vị cho 300 ký tự unicode đầu tiên và xác nhận rằng chỉ các ký tự không hợp lệ bị xóa:
[Fact]
public void validate_that_RemoveInvalidData_only_remove_all_invalid_data()
{
string xmlFormat = "<element>{0}</element>";
string[] allAscii = (Enumerable.Range('\x1', 300).Select(x => ((char)x).ToString()).ToArray());
string[] allAsciiInHexCode = (Enumerable.Range('\x1', 300).Select(x => "&#x" + (x).ToString("X") + ";").ToArray());
string[] allAsciiInHexCodeLoweCase = (Enumerable.Range('\x1', 300).Select(x => "&#x" + (x).ToString("x") + ";").ToArray());
bool hasParserError = false;
IXmlSanitizer sanitizer = new XmlSanitizer();
foreach (var test in allAscii.Concat(allAsciiInHexCode).Concat(allAsciiInHexCodeLoweCase))
{
bool shouldBeRemoved = false;
string xml = string.Format(xmlFormat, test);
try
{
XDocument.Parse(xml);
shouldBeRemoved = false;
}
catch (Exception e)
{
if (test != "<" && test != "&") //these char are taken care of automatically by my convertor so don't need to test. You might need to add these.
{
shouldBeRemoved = true;
}
}
int xmlCurrentLength = xml.Length;
int xmlLengthAfterSanitize = Regex.Replace(xml, @"&#x([0-8BCEF]|1[0-9A-F]);|[\u0000-\u0008\u000B\u000C\u000E-\u001F]", "").Length;
if ((shouldBeRemoved && xmlCurrentLength == xmlLengthAfterSanitize) //it wasn't properly Removed
||(!shouldBeRemoved && xmlCurrentLength != xmlLengthAfterSanitize)) //it was removed but shouldn't have been
{
hasParserError = true;
Console.WriteLine(test + xml);
}
}
Assert.Equal(false, hasParserError);
}
Mặc dù đây là mẹo triển khai hữu ích nhưng nó không thực sự trả lời câu hỏi của tôi. Chúng ta hãy giả định cho các đối số vì lợi ích của việc thực hiện có sự hỗ trợ tỷ lệ đầu tiên của các ký tự không phải BMP, vì vậy các ký tự thay thế là không cần thiết chút nào. –