替换无效XML字符的字符引用

Dou*_*las 5 .net c# xml

我正在使用ADO.NET从SQL Server将一些数据投影为XML。我的某些数据包含在XML中无效的字符,例如CHAR(7)(称为BEL)。

SELECT 'This is BEL: ' + CHAR(7) AS A FOR XML RAW
Run Code Online (Sandbox Code Playgroud)

SQL Server 这样的无效字符编码为数字引用:

<row A="This is BEL: &#x7;" />
Run Code Online (Sandbox Code Playgroud)

但是,即使编码形式在XML 1.0下也是无效的,并且会在XML解析器中引起错误:

var doc = XDocument.Parse("<row A=\"This is BEL: &#x7;\" />");
// XmlException: ' ', hexadecimal value 0x07, is an invalid character. Line 1, position 25.
Run Code Online (Sandbox Code Playgroud)

我想用Unicode替换字符替换所有这些无效的数字引用'?'。我知道如何对未编码的XML执行此操作:

string str = "<row A=\"This is BEL: \u0007\" />";
if (str.Any(c => !XmlConvert.IsXmlChar(c)))
    str = new string(str.Select(c => XmlConvert.IsXmlChar(c) ? c : '?').ToArray());
          // <row A="This is BEL: ?" />
Run Code Online (Sandbox Code Playgroud)

是否有一种直接的方法也可以使其适用于编码的XML?我宁愿避免必须HtmlDecode然后HtmlEncode整个字符串,为了不引入风险比无效字符替换其他变化。

编辑:转换需要在我的C#代码中完成,而不是在SQL中完成,以便将其集中实现。

Ton*_*ton 2

我用正则表达式又做了一次尝试。这应该处理十进制和十六进制字符代码。此外,除了数字编码字符之外,这不会影响任何内容。

public string ReplaceXMLEncodedCharacters(string input)
{
    const string pattern = @"&#(x?)([A-Fa-f0-9]+);";
    MatchCollection matches = Regex.Matches(input, pattern);
    int offset = 0;
    foreach (Match match in matches)
    {
        int charCode = 0;
        if (string.IsNullOrEmpty(match.Groups[1].Value))
            charCode = int.Parse(match.Groups[2].Value);
        else
            charCode = int.Parse(match.Groups[2].Value, System.Globalization.NumberStyles.HexNumber);
        char character = (char)charCode;
        input = input.Remove(match.Index - offset, match.Length).Insert(match.Index - offset, character.ToString());
        offset += match.Length - 1;
    }
    return input;
}
Run Code Online (Sandbox Code Playgroud)