【问题标题】:Need to remove illegal characters in XML string需要去除 XML 字符串中的非法字符
【发布时间】:2016-12-09 12:50:52
【问题描述】:

我必须在 C# 中处理 xml 数据,但是,有时会出现非法 XML 字符。 例如,此 XML 代码将不会被解析,因为它是无效的:

<xml>Another way to write a heart is <3</xml>

XML 解析器会抛出错误,因为它无效,这是有道理的。 虽然,我似乎没有找到一种方法将只有一个“

<xml>Another way to write a heart is &lt;3</xml>

脚注:它可以出现在 xml 中的任何节点中,它本身可能非常大,就像我之前说的,它并非总是发生......

有没有可以处理这个的函数?

【问题讨论】:

  • 真的很困难,因为在 XML 中转义无效字符的全部目的是防止输出无效......您是否无法控制 XML 的生产者?正则表达式在这里可以提供帮助,因为您可以检查有效的标签名称(标签名称不能以数字开头,因此上面的示例可以修复)等等。
  • 问题是,您没有使用 XML。您正在处理的文本字符串有点类似于 XML,但尚未根据 XML 规则正确构造。因此,不要寻找 XML 工具来解决这个问题。正如 Charleh 建议的那样,最好的解决办法是让向您提供此输入的任何人/任何人转而为您提供真正的 XML。

标签: c# xml


【解决方案1】:

我从@IgorKustov 之前的回答中复制粘贴到here

作为删除无效 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;
    }
}

更新:需要说明的是,编码操作会产生一个长度大于或等于a长度的字符串 源字符串。当您将编码的字符串存储在 具有长度限制和验证的字符串列中的数据库 应用中的源字符串长度以适应数据列限制。

【讨论】:

    【解决方案2】:

    对此没有通用解决方案,因为您无法确定是否:

    <xml>You can use <b></b> to highlight stuff in HTML.</xml>.
    

    是一个“错误”,实际上应该被编码:

    <xml>You can use &lt;b&gt;&lt;/b&gt; to highlight stuff in HTML.</xml>.
    

    或者不。

    因此,由于没有通用的解决方案,您只能使用不完善的启发式来检测此类问题。

    C# BCL 中没有内置的启发式方法,您必须自行开发或查找一些外部库。例如,一个简单的启发式方法是查找所有 &lt; 后面没有 [/a-zA-Z0-9]+&gt; 的所有 [/a-zA-Z0-9]+&gt; 并将它们转义。

    启发式算法本质上是不完善的,因此如果您有机会修复系统创建那些损坏的看起来像 XML 但不是文件的文件,这将是一个更好的解决方案。

    【讨论】:

    • 这是我用来解决的问题,此时我可以用这个正则表达式匹配错误的 XML 字符:)觉得遇到其他情况就多加点表情吧……谢谢!
    • 扩展正则表达式以匹配 :)
    • @stijnpiron: [/a-zA-Z0-9]*[_/a-zA-Z0-9]* 在语义上等同于[_/a-zA-Z0-9]*
    • @Heinzi:不,不是。前者首先限制下划线,后者则没有。
    • @OttoAbnormalverbraucher:如果第一个量词是+(或缺失)而不是*,它会。就目前而言,_abc 是一个有效匹配,由第一个字符组的 0 倍和第二个字符组的 4 倍组成。
    【解决方案3】:

    Check this link 您可以使用正则表达式来修复 xml 字符串。这是链接中的代码:

    public static String repair(String xml) {
        Pattern pattern = Pattern.compile("(<attribute name=\"[^\"]+\">)(.*?)(</attribute>)");
        Matcher m = pattern.matcher(xml);
        StringBuffer buf = new StringBuffer(xml.length() + xml.length() / 32);
        while (m.find()) {
            String escaped = StringEscapeUtils.escapeXml(m.group(2));
            m.appendReplacement(buf, m.group(1) + escaped + m.group(3));
        }
        m.appendTail(buf);
        return buf.toString();
    }
    

    根据您的 xml 字符串的大小,性能可能是一个问题。但至少据我所知,没有解析器可以读取带有非法字符的 xml 并删除它们。

    【讨论】:

      猜你喜欢
      • 2011-04-28
      • 1970-01-01
      • 2018-10-21
      • 2017-05-24
      • 2012-04-28
      • 1970-01-01
      相关资源
      最近更新 更多