2016-12-09 2 views
0

C#でxmlデータを処理する必要がありますが、時には不正なXML文字が存在することがあります。 たとえば、このXMLコードは、それが無効であるとして解析できないだろう:それは理にかなっている、有効ではありませんので、XML文字列内の不正な文字を削除する必要があります

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

XMLパーサがエラーをスローします。 しかし、私は "<"と "& lt;"のどちらかを置き換える方法はないようですが、

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

脚注を:ようパーサが受け取ることになります...それはすべての時間に発生していない、それはかなり大きなそのものできるXML内の任意のノードでoccureことができると私は前に言ったよう

これを処理できる関数はありますか?

+1

本当に難しいのは、XMLで無効な文字をエスケープすることは、出力が無効になることです。あなたはXMLのプロデューサを制御できませんか?有効なタグ名(タグ名は数字で始めることはできないので、上記の例は修正可能です)などを調べることができるので、Regexがここで助けてくれるでしょう。 – Charleh

+2

問題は、XMLで作業していないことです。 XMLに幾分似ていますが、XMLの規則に従って正しく構築されていない文字列を扱っています。したがって、この問題を解決するためのXMLツールを検討しないでください。 Charlehが示唆しているように、最良の解決策は、あなたにこの入力を提供している人の誰かに、本物のXMLを提供することに切り替えることです。 –

答えて

2

は、これに何ら一般ソリューションはありません。

したがって、一般的な解決法はないので、不完全なヒューリスティックのみを使用して、このような問題を検出できます。

C#BCLにはヒューリスティックは組み込まれていません。独自のロールバックや外部ライブラリの検索が必要になります。たとえば、簡単なヒューリスティックは、[/a-zA-Z0-9]+>の後ろにないすべての<を見つけてエスケープすることです。

ヒューリスティックは本質的に完全ではないので、ファイルを作成する機会があれば、これははるかに良い解決策になります。

+1

これは私が解決するために使用したアンカーです。この時点で間違ったXML文字をこのREGEX式に一致させることができます:<(?![a-zA-Z0-9] +>) 他の状況に遭遇したときの表現...ありがとう! – stijnpiron

+0

と一致する正規表現を展開しました。 <(!![/ a-zA-Z0-9] * [_/a-zA-Z0-9] *) – stijnpiron

+0

@stijnpiron: '[/ a-zA -Z0-9] * [_/a-zA-Z0-9] * 'は意味的に' [_/a-zA-Z0-9] * 'と同等です。 – Heinzi

0

Check this link xml文字列を修復するためにregexを使用できます。これはリンクのコードです:

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に不正な文字を読み込んで削除できるパーサはありません。

<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>. 

かあなたがいるかどうかを判断する方法がないので

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; 
    } 
} 

そして、私はあなたが XmlConvert.EncodeNameメソッドを使用することをお勧め無効なXML文字をエスケープする方法として:ここに小さなサンプルです。ここで少量のサンプルである:

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; 
    } 
} 

更新:長さが大きいか ソース・ストリングの長さよりも等しいと符号化操作は文字列を生成することが言及されるべきである。コード化された文字列を に格納し、長さ制限付きの文字列にデータベースを格納し、データ列の制限に合わせて ソース文字列の長さを検証することが重要です。

関連する問題