잘못된 XML 문자가 포함 된 문자열이 있습니다. 문자열을 구문 분석하기 전에 잘못된 XML 문자를 어떻게 이스케이프 (또는 제거) 할 수 있습니까?
잘못된 XML 문자가 포함 된 문자열이 있습니다. 문자열을 구문 분석하기 전에 잘못된 XML 문자를 어떻게 이스케이프 (또는 제거) 할 수 있습니까?
답변:
잘못된 XML 문자를 제거하는 방법으로 XmlConvert.IsXmlChar 메서드 를 사용하는 것이 좋습니다 . .NET Framework 4 이후에 추가되었으며 Silverlight에서도 제공됩니다. 다음은 작은 샘플입니다.
void Main() {
string content = "\v\f\0";
Console.WriteLine(IsValidXmlString(content)); // False
content = RemoveInvalidXmlChars(content);
Console.WriteLine(IsValidXmlString(content)); // True
}
static string RemoveInvalidXmlChars(string text) {
var validXmlChars = text.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray();
return new string(validXmlChars);
}
static bool IsValidXmlString(string text) {
try {
XmlConvert.VerifyXmlChars(text);
return true;
} catch {
return false;
}
}
유효하지 않은 XML 문자를 이스케이프하는 방법으로 XmlConvert.EncodeName 메서드 를 사용하는 것이 좋습니다 . 다음은 작은 샘플입니다.
void Main() {
const string content = "\v\f\0";
Console.WriteLine(IsValidXmlString(content)); // False
string encoded = XmlConvert.EncodeName(content);
Console.WriteLine(IsValidXmlString(encoded)); // True
string decoded = XmlConvert.DecodeName(encoded);
Console.WriteLine(content == decoded); // True
}
static bool IsValidXmlString(string text) {
try {
XmlConvert.VerifyXmlChars(text);
return true;
} catch {
return false;
}
}
업데이트 : 인코딩 작업이 소스 문자열의 길이보다 크거나 같은 길이의 문자열을 생성한다는 점을 언급해야합니다. 길이 제한이있는 문자열 열의 데이터베이스에 인코딩 된 문자열을 저장하고 데이터 열 제한에 맞게 앱에서 소스 문자열 길이의 유효성을 검사 할 때 중요 할 수 있습니다.
XmlConvert.VerifyXmlChars
인수에 잘못된 문자가 포함 된 경우 예외를 throw하지 않고 null 문자열을 반환하고 포함 된 모든 문자가 유효한 경우 인수를 반환합니다. 시도해보십시오 return XmlConvert.VerifyXmlChars (text) != null
.
using System;
using System.Security;
class Sample {
static void Main() {
string text = "Escape characters : < > & \" \'";
string xmlText = SecurityElement.Escape(text);
//output:
//Escape characters : < > & " '
Console.WriteLine(xmlText);
}
}
xml을 작성하는 경우 프레임 워크에서 제공하는 클래스를 사용하여 xml을 만듭니다. 탈출이나 그 어떤 것도 신경 쓰지 않아도됩니다.
Console.Write(new XElement("Data", "< > &"));
출력됩니다
<Data>< > &</Data>
형식이 잘못된 XML 파일을 읽어야하는 경우 정규식을 사용 하지 마십시오 . 대신 Html Agility Pack을 사용하십시오 .
<Data>&</Data>
?
Irishman에서 제공하는 RemoveInvalidXmlChars 메서드는 대리 문자를 지원하지 않습니다. 테스트하려면 다음 예제를 사용하십시오.
static void Main()
{
const string content = "\v\U00010330";
string newContent = RemoveInvalidXmlChars(content);
Console.WriteLine(newContent);
}
이것은 빈 문자열을 반환하지만 안됩니다! U + 10330 문자는 유효한 XML 문자 이므로 "\ U00010330"을 반환해야 합니다.
대리 문자를 지원하려면 다음 방법을 사용하는 것이 좋습니다.
public static string RemoveInvalidXmlChars(string text)
{
if (string.IsNullOrEmpty(text))
return text;
int length = text.Length;
StringBuilder stringBuilder = new StringBuilder(length);
for (int i = 0; i < length; ++i)
{
if (XmlConvert.IsXmlChar(text[i]))
{
stringBuilder.Append(text[i]);
}
else if (i + 1 < length && XmlConvert.IsXmlSurrogatePair(text[i + 1], text[i]))
{
stringBuilder.Append(text[i]);
stringBuilder.Append(text[i + 1]);
++i;
}
}
return stringBuilder.ToString();
}
다음은 위 메서드 RemoveInvalidXmlChars의 최적화 된 버전입니다.이 메서드는 모든 호출에서 새 배열을 만들지 않으므로 GC에 불필요하게 스트레스를줍니다.
public static string RemoveInvalidXmlChars(string text)
{
if (text == null)
return text;
if (text.Length == 0)
return text;
// a bit complicated, but avoids memory usage if not necessary
StringBuilder result = null;
for (int i = 0; i < text.Length; i++)
{
var ch = text[i];
if (XmlConvert.IsXmlChar(ch))
{
result?.Append(ch);
}
else if (result == null)
{
result = new StringBuilder();
result.Append(text.Substring(0, i));
}
}
if (result == null)
return text; // no invalid xml chars detected - return original text
else
return result.ToString();
}
?.
구문 은 무엇입니까 ? 줄에 result?.Append(ch);
?
// Replace invalid characters with empty strings.
Regex.Replace(inputString, @"[^\w\.@-]", "");
정규식 패턴 [^ \ w. @-]은 단어 문자, 마침표, @ 기호 또는 하이픈이 아닌 모든 문자와 일치합니다. 단어 문자는 문자, 십진수 또는 밑줄과 같은 구두점 커넥터입니다. 이 패턴과 일치하는 모든 문자는 대체 패턴으로 정의 된 문자열 인 String.Empty로 대체됩니다. 사용자 입력에 추가 문자를 허용하려면 해당 문자를 정규식 패턴의 문자 클래스에 추가하십시오. 예를 들어 정규식 패턴 [^ \ w. @-\ %]은 입력 문자열에 백분율 기호와 백 슬래시도 허용합니다.
Regex.Replace(inputString, @"[!@#$%_]", "");
이것도 참조하십시오 :
XML 이름 태그에서 잘못된 문자 제거-RegEx C #
다음은 지정된 XML 문자열에서 문자를 제거하는 함수입니다.
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace XMLUtils
{
class Standards
{
/// <summary>
/// Strips non-printable ascii characters
/// Refer to http://www.w3.org/TR/xml11/#charsets for XML 1.1
/// Refer to http://www.w3.org/TR/2006/REC-xml-20060816/#charsets for XML 1.0
/// </summary>
/// <param name="content">contents</param>
/// <param name="XMLVersion">XML Specification to use. Can be 1.0 or 1.1</param>
private void StripIllegalXMLChars(string tmpContents, string XMLVersion)
{
string pattern = String.Empty;
switch (XMLVersion)
{
case "1.0":
pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|7F|8[0-46-9A-F]9[0-9A-F])";
break;
case "1.1":
pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|[19][0-9A-F]|7F|8[0-46-9A-F]|0?[1-8BCEF])";
break;
default:
throw new Exception("Error: Invalid XML Version!");
}
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
if (regex.IsMatch(tmpContents))
{
tmpContents = regex.Replace(tmpContents, String.Empty);
}
tmpContents = string.Empty;
}
}
}
string XMLWriteStringWithoutIllegalCharacters(string UnfilteredString)
{
if (UnfilteredString == null)
return string.Empty;
return XmlConvert.EncodeName(UnfilteredString);
}
string XMLReadStringWithoutIllegalCharacters(string FilteredString)
{
if (UnfilteredString == null)
return string.Empty;
return XmlConvert.DecodeName(UnfilteredString);
}
이 간단한 방법은 잘못된 문자를 동일한 값으로 대체하지만 XML 컨텍스트에서 허용됩니다.
문자열을 쓰려면 XMLWriteStringWithoutIllegalCharacters (string UnfilteredString)를 사용하십시오.
문자열을 읽으려면 XMLReadStringWithoutIllegalCharacters (string FilteredString)를 사용하십시오.