14

.NETXmlTextWriterは無効なxmlファイルを作成します。

XMLでは、「水平タブ」(	)のように一部の制御文字が許可されますが、「垂直タブ」()のように許可されないものもあります。(仕様を参照してください。)

XMLで許可されていないUTF-8制御文字を含む文字列があります。文字をエスケープしますが、結果のXMLはもちろん無効です
XmlTextWriter

XmlTextWriter違法なXMLファイルが生成されないようにするにはどうすればよいですか?

または、でこれを行うことXmlTextWriterができない場合、XMLで許可されていない特定の制御文字を文字列から削除するにはどうすればよいですか?

コード例:

using (XmlTextWriter writer =
  new XmlTextWriter("test.xml", Encoding.UTF8))
{
  writer.WriteStartDocument();
  writer.WriteStartElement("Test");
  writer.WriteValue("hello \xb world");
  writer.WriteEndElement();
  writer.WriteEndDocument();
}

出力:

<?xml version="1.0" encoding="utf-8"?><Test>hello &#xB; world</Test>
4

3 に答える 3

13

この動作のドキュメントは、WriteStringメソッドのドキュメントに隠されていますが、クラス全体に適用されるようです。

Createを使用して作成されたXmlWriterのデフォルトの動作は、0x〜0x1Fの範囲の文字値(空白文字0x9、0xA、および0xDを除く)を書き込もうとしたときにArgumentExceptionをスローすることです。これらの無効なXML文字は、CheckCharactersプロパティをfalseに設定してXmlWriterを作成することで書き込むことができます。これを行うと、文字が数字のエンティティ(&#0; から&#0x1F)に置き換えられます。さらに、new演算子で作成されたXmlTextWriterは、デフォルトで無効な文字を数字のエンティティに置き換えます。

したがって、XmlTextWriterクラスを使用しているため、無効な文字を書き込んでしまうようです。より良い解決策は、代わりにXmlWriterクラスを使用することです。

于 2011-11-24T11:55:16.900 に答える
3

同じ問題に苦しんでいたときにこの質問を見つけたところ、正規表現で解決することになりました。

return Regex.Replace(s, @"[\u0000-\u0008\u000B\u000C\u000E-\u001F]", "");

それが代替ソリューションとして誰かを助けることを願っています。

于 2013-06-26T21:31:53.737 に答える
1

組み込みの.NETエスケープ機能もSecurityElement.Escape、適切にエスケープ/ストリップしません。

  • アプリケーションがファイルと対話する唯一のアプリケーションである場合は、ライターとリーダーの両方にCheckCharacters設定できます。falseただし、結果のXMLファイルは技術的には無効です。

見る:

XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.CheckCharacters = false;
var sb = new StringBuilder();
var w = XmlWriter.Create(sb, xmlWriterSettings);
w.WriteStartDocument();
w.WriteStartElement("Test");
w.WriteString("hello \xb world");
w.WriteEndElement();
w.WriteEndDocument();
w.Close();
var xml = sb.ToString();
  • (デフォルトでは)に設定CheckCharactersするtrueのが少し厳しすぎる場合は、単に例外をスローするため、無効なXML文字に対してより寛容な代替アプローチは、それらを削除することです。

少しグーグルするとホワイトリストXmlTextEncoderが生成されましたが、ウィキペディアの有効なXML文字によると、特定のコンテキストでのみ有効であるDELU + 007F–U + 0084、U + 0086–U+009Fの範囲のその他の文字も削除されます。 RFCは、推奨されていないがまだ有効な文字として言及しています。

public static class XmlTextExtentions
{
    private static readonly Dictionary<char, string> textEntities = new Dictionary<char, string> {
        { '&', "&amp;"}, { '<', "&lt;" }, { '>', "&gt;" }, 
        { '"', "&quot;" }, { '\'', "&apos;" }
    };
    public static string ToValidXmlString(this string str)
    {
        var stripped = str
            .Select((c,i) => new 
            { 
                c1 = c, 
                c2 = i + 1 < str.Length ? str[i+1]: default(char),
                v = XmlConvert.IsXmlChar(c),
                p = i + 1 < str.Length ? XmlConvert.IsXmlSurrogatePair(str[i + 1], c) : false,
                pp = i > 0 ? XmlConvert.IsXmlSurrogatePair(c, str[i - 1]) : false
            })
            .Aggregate("", (s, c) => {                  
                if (c.pp)
                    return s;
                if (textEntities.ContainsKey(c.c1))
                    s += textEntities[c.c1];
                else if (c.v)
                    s += c.c1.ToString();
                else if (c.p)
                    s += c.c1.ToString() + c.c2.ToString();
                return s;
            });
        return stripped;
    }
}

DELこれは、すべてのXmlTextEncoderテストに合格します。ただしXmlConvert.IsXmlChar、ウィキペディアとスペックマークを有効な(推奨されない)文字として削除することを期待するテストを除きます。

于 2011-11-24T21:37:38.690 に答える