修复错误的XML文件(例如,未转义和等等)

时间:2011-05-16 14:25:59

标签: .net xml xmltextreader

我从第三方获得了一个我必须在我的应用程序中导入的XML文件,并且XML包含未转义和未转换的元素。在内部文本中,他们不会解决这个问题!所以我的问题是处理这个问题的最佳方法是什么?

这个XML非常大,而且修复速度必须很快,我的第一个解决方案就是替换&有&符号的字符,但实际上我不喜欢这个“解决方案”,原因很明显。我不知道如何使用XmlStringReader与这样的XML,因为在这样的行上抛出异常,所以我不能在内部文本上使用HtmlEncode。我试图将XmlTextReader Settings.CheckCharacters设置为false但没有结果。

以下是样本,&在元素中,并且在该字段中可以是某些公司名称中的任何内容,因此我的替换修复可能不适用于某些其他公司名称,我想以某种方式使用HtmlEncode,但当然仅在内部文本上。

<komitent ID="001398">
  <sifra>001398</sifra>
  <redni_broj>001398</redni_broj>
  <naziv>LJUBICA & ŽARKO</naziv>
  <adresa1>Odvrtnica 27</adresa1>
  <adresa2></adresa2>
  <drzava>HRVATSKA</drzava>
  <grad>Zagreb</grad>
</komitent>

6 个答案:

答案 0 :(得分:4)

下面的关键信息是,除非您知道输入文件的确切格式,并保证与XML的任何偏差是一致的,否则您无法以编程方式进行修复,而不会担心您的修补程序不正确。

当且仅在以下情况下,将&替换为&amp;进行修复是可接受的解决方案:

  1. 这些数据没有可接受的格式良好的来源。

    • 正如@Darin Dimitrov发表评论,试着寻找更好的提供商,或者让这个提供商来修复它。
    • JSON(例如)比形成不良的XML更好,即使你没有使用javascript。
  2. 这是一次性(或至少非常罕见)的导入。

    • 如果您必须在运行时获取此内容,则此解决方案将无效。
  3. 您可以继续迭代,为其设计新的修补程序,在遇到问题时为每个问题添加解决方案。

    • 您可能会发现,一旦您通过转义&字符“修复”它,就会出现其他错误。
  4. 您有资源手动检查“已修复”数据的完整性。

    • 您“修复”的错误可能比您意识到的更为微妙。
  5. 文档中没有格式正确的实体 -

    • 只需将&替换为&amp;,就会错误地将&quot;更改为&amp;quot;。你可能能够解决这个问题,但不要天真地对它有多么棘手(实体可能在DTD中定义,可能指的是unicode代码点......)

    • 如果它是一个行为异常的特定元素,您可以考虑使用<![CDATA ]]>包装元素的内容,但这仍然依赖于您能够找到开始和结束标签可靠。

答案 1 :(得分:2)

首先改变你的心态。输入不是XML,因此不要将其称为XML。甚至不要使用“xml”标记您的问题。事实上它不是XML意味着您不能使用任何XML工具,并且您无法获得XML数据交换的任何好处。您正在处理没有规范且没有任何工具的专有格式。像对待任何其他专有格式一样对待它 - 尝试发现您获得的规范,并为其编写解析器。

答案 2 :(得分:2)

如果你知道文件的标签,并希望“标记”可能有可疑数据的标签内的文字,你可以这样做:

private static string FixBadXmlText(string xmlText)
{           
    var unreliableTextTags = new[] { "message", "otherdata", "stacktrace", "innerexception" };

    foreach(var tag in unreliableTextTags)
    {
        string openTag = "<" + tag + ">";
        string closeTag = "</" + tag + ">";
        xmlText = xmlText.Replace(openTag, openTag + "<![CDATA[").Replace(closeTag, "]]>" + closeTag);
    }

    return xmlText;
}

CDATA Section<![CDATA[ {your text here} ]]>)内的任何内容都不会被XML解析器解释,因此不需要进行转义。当我想解析一些没有正确转义输入的糟糕的XML时,这对我有所帮助。

答案 3 :(得分:0)

由于您的起始XML是错误的,因此无法使用任何XmlReaders,因为它们无法正确读取它。

如果只有XML节点的值不是htmlEncoded,那么你必须手动读取行,解析(获取xml节点名称及其值),编码并输出到新文件。

我们经常会遇到类似的情况所以我理解你的痛苦 - 大部分时间,错误都有一些“规则”,所以我猜这里他们没有编码商业名称(也许是街道名称),所以你可以只搜索那个字符串<naziv>,它正在关闭标签</naziv>和HtmlEncode之间的所有内容。此外,由于它的商业名称,它不会有换行符,这可以让你的生活相当轻松......

答案 4 :(得分:0)

您可以尝试使用正则表达式,具体取决于结构的复杂程度:

Regex mainSplitter = new Regex("<komitent ID=\"([0-9]*)\">(.*?)</komitent>");
Regex nazivFinder = new Regex("<naziv>(.*?)</naziv>");

foreach (Match item in mainSplitter.Matches(test))
{
    Console.WriteLine(item);

    string naziv = null;

    Match node = nazivFinder.Match(item.Groups[2].Value);
    if (node != null)
        naziv = node.Groups[1].Value;
}

答案 5 :(得分:0)

您可以将文件作为XPL处理,甚至使用XPL解析器将这些文件转换为有效的XML。 XPL(可扩展进程语言)就像XML一样,但解析器允许XML在文本字段中使用“特殊字符”。因此,您实际上可以通过XPL进程运行无效的XML文件(由于特殊字符而无效)。在某些情况下,您可以使用XPL处理器而不是XML处理器。您还可以使用它来预处理无效文件,而不会造成任何性能损失。 Artificial Intelligence, XML, and Java Concurrency