从XML字符串中删除非法字符

时间:2011-03-23 17:25:33

标签: c# xml

我有一个包含一些XML的字符串。例如:

<foo>
    <bar>this is < than this</bar>
</foo>

我需要先删除illagal字符,然后再将其加载到XmlDocument中。

任何想法。

提前致谢

4 个答案:

答案 0 :(得分:5)

  

我有一个包含一些Xml的字符串。

不,不。你有一些类似XML的文本格式不正确。一旦它全部粘在一起,就很难找到特殊的角色。哦,你可以尝试寻找“&lt;”或“&gt;”,但无论如何都会出现。我的建议是回过头来看看那个字符串来自哪里。更改该代码,使其处理特殊字符。

在没有任何其他选项的情况下,我可能暂时忽略XML工具(因为当你试图给它们字符串时它们会抛出)并且执行某种打开/关闭的运行计数(奇数/甚至是特殊字符的引号)。一旦遇到&lt;,例如,在遇到&gt;之前,不允许再使用另一个。不幸的是你不能使用&lt;等等属性,所以我不知道你会对<foo p1="a<a">做什么,但至少你可以修复<foo>a<A</foo>。 (假设他们永远不会在标签名称中加上&lt;在第二个标记名称中,意味着您需要备份并转义第一个。)一旦遇到&gt;,就不能再使用另一个了。等等。我的同情心。

答案 1 :(得分:1)

我认为你在这里做的最好的事情就是对你可能会看到的内容做出明智的猜测,并尝试尽可能地处理它们。最重要的是要确保如果您的规则失败,您不会损坏其他数据 - 不做任何事情而优雅地中止,并且警告管理员通常不理想,但是您可能获得的最好。

在你给出的例子中,&lt;之后似乎有一个空格。在数据字符串中跟随空格,而&lt;形成标签的一部分不是。你能利用它吗?

根据我使用不符合规格的文件的经验,你必须使用你所给予的小碎屑,并祈祷你选择的任何神都不会解开进一步。

对不起。 ;)

编辑 -

我刚刚发生了一件事......您正在以严格的预定义格式处理数据吗?例如,它会在标签中包含可选参数吗?如果没有,你可能会非常偷偷摸摸(并且通过使用模式使硬化的开发人员稍微哭泣)。

例如 - 如果你知道你总是会得到像这样的标签

<myData>
  <MyFirstTag>Hello, I contain illegal < data</MyFirstTag>
  <moreData>and I am just plain <B>stupid</B></moreData>
</myData>

您可以尝试使用一些已知且唯一的字符串(可能是guid?)来标记字段定义。

knownstring1
  knownstring2Hello, I contain illegal < dataendknownstring2
  knownstring3and I am just plain <B>stupid</B>endknownstring3
endknownstring1

然后你可以对非法字符进行替换,然后将标记准备好导入到XMLDocument中。

我知道,这也让我感到不寒而栗,但有时您获得的数据需要您诉诸于肮脏的黑客。

答案 2 :(得分:1)

这是一种非常常见的使用标记的方案,这种标记已经以某种方式遗留给您。 2种一般可能性:

1)标记是由您可能或可能无法访问的错误代码生成的。您可能会发现坏点是重复且可预测的,您可以使用自己的代码减少问题:正则表达式等。在可以修复生成代码的快乐情况下,显然可以解决这个问题。< / p>

2)标记是由不了解/关心他们正在做什么的人产生的。这是一个人的问题。不要尝试使用代码修复它。你必须通过与正在这样做的人交谈并以某种方式处理政治来处理它。看看光明的一面,也许你可以让老板去做。

答案 3 :(得分:0)

这是一个修复xml中错误的工具:

#!/usr/bin/env perl

# Fixes unescaped "<" and "&" in between tags.

use strict;
use warnings;

use Encode qw( encode decode );

sub fix_xml {
    my ($broken_xml) = @_;

    my $enc;
    if    ( $_[0] =~ /^\xEF\xBB\xBF/ ) { $enc = 'UTF-8';    }
    elsif ( $_[0] =~ /^\xFF\xFE/     ) { $enc = 'UTF-16le'; }
    elsif ( $_[0] =~ /^\xFE\xFF/     ) { $enc = 'UTF-16be'; }
    elsif (substr($_[0], 0, 100) =~ /^[^>]* encoding="([^"]+)"/) { $enc = $1; }
    else                               { $enc = 'UTF-8';    }

    $broken_xml = decode($enc, $_[0], Encode::FB_CROAK | Encode::LEAVE_SRC);

    my $name   = qr/(?:\w+:)?\w+/x;
    my $value  = qr/(?: '[^']+' | "[^"]+" )/x;
    my $s      = qr/\s/x;
    my $attrib = qr/$name $s* = $s* $value/x;

    my $fixed_xml = '';
    for ($broken_xml) {
        /\G \z /xcg && last;

        /\G ( (?: [^<&]+ | &\#?\w+; )+               ) /xscg && do { $fixed_xml .= $1; redo };  # Text
        /\G ( < $name (?: $s+ $attrib )* $s* \/? >   ) /xscg && do { $fixed_xml .= $1; redo };  # Start or empty tag
        /\G ( <\/ $name $s* >                        ) /xscg && do { $fixed_xml .= $1; redo };  # End tag
        /\G ( <!-- (?:(?! -- ).)* -->                ) /xscg && do { $fixed_xml .= $1; redo };  # Comment
        /\G ( <!\[CDATA\[ (?:(?! \]\]> ).)* \]\]>    ) /xscg && do { $fixed_xml .= $1; redo };  # CDATA
        /\G ( <? $s* $name (?: $s+ $attrib )* $s* ?> ) /xscg && do { $fixed_xml .= $1; redo };  # Decl

        # Something illegal!
        /\G ( < ) /xscg && do { $fixed_xml .= "&#lt;";  redo };  # Unescaped "<"
        /\G ( & ) /xscg && do { $fixed_xml .= "&#amp;"; redo };  # Unescaped "&"

        die("Don't know how to fix character at position " . pos() . "\n");
    }

    return encode($enc, $fixed_xml);
}

die("usage: $0 file.xml") if !@ARGV || $ARGV[0] eq '/?' || $ARGV[0] eq '-h' || $ARGV[0] eq '--help';

my $broken_xml;
{
    open(my $fh, '<', $ARGV[0])
       or die("Can't open \"$ARGV[0]\": $!\n");
    binmode($fh);
    local $/;
    $broken_xml = <$fh>;
}

binmode(STDOUT);
print fix_xml($broken_xml);

它没有检测到所有问题(例如属性中未转义的“&amp;”),但它确实检测并修复了您所询问的问题。

未测试。