10

XML への文字列エスケープを調べたところ、非常に役立つことがわかりました。

同様のことをしたいと思います: XML 属性で使用される文字列をエスケープします。

文字列には \r\n が含まれる場合があります。XmlWriter クラスは \r\n -> のようなものを生成します。

私が現在使用しているソリューションには、XmlWriter と StringBuilder が含まれており、かなり醜いです。

ヒントはありますか?

Edit1: LarsH
を失望させて申し訳ありません。私の最初のアプローチを購入するのは

public static string XmlEscapeAttribute(string unescaped)
{
    XmlDocument doc = new XmlDocument();
    XmlAttribute attr= doc.CreateAttribute("attr");
    attr.InnerText = unescaped;
    return attr.InnerXml;
}

それは動作しません。XmlEscapeAttribute("Foo\r\nBar")結果として"Foo\r\nBar"

.NET Reflector を使用して、XmlTextWriter が属性をエスケープする方法を調べました。内部の XmlTextEncoder クラスを使用しています...

現在、次のようなロックを使用している私の方法:

public static string XmlEscapeAttribute(string unescaped)
{
    if (String.IsNullOrEmpty(unescaped)) return unescaped;

    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    StringBuilder sb = new StringBuilder();
    XmlWriter writer = XmlWriter.Create(sb, settings);

    writer.WriteStartElement("a");
    writer.WriteAttributeString("a", unescaped);
    writer.WriteEndElement();
    writer.Flush();
    sb.Length -= "\" />".Length;
    sb.Remove(0, "<a a=\"".Length);

    return sb.ToString();
}

それは醜く、おそらく遅いですが、うまくXmlEscapeAttribute("Foo\r\nBar")いきます:"Foo&#xD;&#xA;Bar"

編集2:

SecurityElement.Escape(unescaped);

どちらも機能しません。

Edit3 (最終):

Lars からの非常に有益なコメントをすべて使用すると、最終的な実装は次のようになります。

: は.Replace("\r", "&#xD;").Replace("\n", "&#xA;");有効な XML には必要ありません。あくまで美容対策です!

    public static string XmlEscapeAttribute(string unescaped)
    {

        XmlDocument doc = new XmlDocument();
        XmlAttribute attr= doc.CreateAttribute("attr");
        attr.InnerText = unescaped;
        // The Replace is *not* required!
        return attr.InnerXml.Replace("\r", "&#xD;").Replace("\n", "&#xA;");
    }

結局のところ、これは有効な XML であり、標準に準拠した XML パーサーによって解析されます。

<response message="Thank you,
LarsH!" />
4

3 に答える 3

9

参考にさせていただいた解決策を修正して、いかがでしょうか

public static string XmlEscape(string unescaped)
{
    XmlDocument doc = new XmlDocument();
    var node = doc.CreateAttribute("foo");
    node.InnerText = unescaped;
    return node.InnerXml;
}

私がしたことは、CreateElement() を CreateAttribute() に変更したことだけです。属性ノード タイプには、InnerText および InnerXml プロパティがあります。

これをテストする環境はありませんが、動作するかどうか知りたいです。

更新:または、より簡単に、リンク先の質問に対する別の回答で提案されているようにSecurityElement.Escape()を使用します。これは引用符をエスケープするので、属性テキストに使用するのに適しています。

更新 2: XML を適切な形式にするために、属性値でキャリッジ リターンとライン フィードをエスケープする必要がないことに注意してください。他の理由でエスケープしたい場合は、String.replace() を使用して実行できます。

SecurityElement.Escape(unescaped).Replace("\r", "&#xD;").Replace("\n", "&#xA;");

また

return node.InnerXml.Replace("\r", "&#xD;").Replace("\n", "&#xA;");
于 2010-12-16T18:53:09.683 に答える
-3

役立つ場合は、いくつかの言語で、createCDATASectionを使用してすべてのXML特殊文字を回避します。

それはこのようなものを追加します:

<tag><![CDATA[ <somecontent/> ]]></tag>
于 2010-12-16T19:04:32.480 に答える