web-dev-qa-db-ja.com

XMLへの文字列エスケープ

XML要素のコンテンツを埋めるために使用できる文字列のエスケープとエスケープ解除に使用できるC#関数はありますか?

VSTS 2008 + C#+ .Net 3.0を使用しています。

編集1:シンプルで短いXMLファイルを連結しており、シリアル化を使用していないので、手動でXML文字を明示的にエスケープする必要があります。たとえば、a<b into <foo></foo>ので、エスケープ文字列a<bそして、それを要素fooに入れます。

88
George2
public static string XmlEscape(string unescaped)
{
    XmlDocument doc = new XmlDocument();
    XmlNode node = doc.CreateElement("root");
    node.InnerText = unescaped;
    return node.InnerXml;
}

public static string XmlUnescape(string escaped)
{
    XmlDocument doc = new XmlDocument();
    XmlNode node = doc.CreateElement("root");
    node.InnerXml = escaped;
    return node.InnerText;
}
71
Darin Dimitrov
118
Dana Holt

編集:あなたは「私はシンプルで短いXMLファイルを連結しており、シリアル化を使用していないので、手動でXML文字を明示的にエスケープする必要がある」と言います。

私は強く手でそれをしないことを勧めます。 XML APIを使用してすべてを実行します。元のファイルを読み取り、必要に応じて2つを1つのドキュメントにマージします(おそらくXmlDocument.ImportNode)、それからもう一度書きます。独自のXMLパーサー/フォーマッターを作成する必要はありません。シリアル化はここではやや無関係です。

あなたがしようとしていることの正確で短いが完全な例を私たちに与えることができれば、私たちはおそらくあなたがそもそも逃げることを心配する必要を避けるのを助けることができるでしょう。


元の回答

あなたが何を意味するかは完全には明らかではありませんが、通常はXML APIがこれを行います。ノードにテキストを設定すると、必要なものはすべて自動的にエスケープされます。例えば:

LINQ to XMLの例:

using System;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        XElement element = new XElement("tag",
                                        "Brackets & stuff <>");

        Console.WriteLine(element);
    }
}

DOMの例:

using System;
using System.Xml;

class Test
{
    static void Main()
    {
        XmlDocument doc = new XmlDocument();
        XmlElement element = doc.CreateElement("tag");
        element.InnerText = "Brackets & stuff <>";
        Console.WriteLine(element.OuterXml);
    }
}

両方の例からの出力:

<tag>Brackets &amp; stuff &lt;&gt;</tag>

もちろん、XMLエスケープが必要だと仮定しています。そうでない場合は、詳細を投稿してください。

37
Jon Skeet

1行のエスケープを@seheに感謝します。

var escaped = new System.Xml.Linq.XText(unescaped).ToString();

それに1行のエスケープを追加します。

var unescapedAgain = System.Xml.XmlReader.Create(new StringReader("<r>" + escaped + "</r>")).ReadElementString();
24
Keith Robertson

ジョージ、それは簡単です。 XMLを処理するには、常にXML APIを使用してください。彼らはあなたのためにすべての脱出と脱出を行います。

文字列を追加してXMLを作成しないでください。

8
John Saunders

そして、私がこの質問を見つけたときのように、たとえばXMLシリアル化から読み取るときなど、XMLノード名をエスケープするには、最も簡単な方法を使用します。

XmlConvert.EncodeName(string nameToEscape)

また、XML要素のスペースと無効な文字をエスケープします。

http://msdn.Microsoft.com/en-us/library/system.security.securityelement.escape%28VS.80%29.aspx

4
CharlieBrown

警告:ネクロマンシング

それでも、Darin Dimitrovの回答+ System.Security.SecurityElement.Escape(string s)は完全ではありません。

XML 1.1では、最も簡単で安全な方法は、すべてをエンコードすることです。
好む &#09;は\ tです。
XML 1.0ではまったくサポートされていません。
XML 1.0の場合、1つの可能な回避策は、文字を含むテキストをbase-64エンコードすることです。

//string EncodedXml = SpecialXmlEscape("привет мир");
//Console.WriteLine(EncodedXml);
//string DecodedXml = XmlUnescape(EncodedXml);
//Console.WriteLine(DecodedXml);
public static string SpecialXmlEscape(string input)
{
    //string content = System.Xml.XmlConvert.EncodeName("\t");
    //string content = System.Security.SecurityElement.Escape("\t");
    //string strDelimiter = System.Web.HttpUtility.HtmlEncode("\t"); // XmlEscape("\t"); //XmlDecode("&#09;");
    //strDelimiter = XmlUnescape("&#59;");
    //Console.WriteLine(strDelimiter);
    //Console.WriteLine(string.Format("&#{0};", (int)';'));
    //Console.WriteLine(System.Text.Encoding.ASCII.HeaderName);
    //Console.WriteLine(System.Text.Encoding.UTF8.HeaderName);


    string strXmlText = "";

    if (string.IsNullOrEmpty(input))
        return input;


    System.Text.StringBuilder sb = new StringBuilder();

    for (int i = 0; i < input.Length; ++i)
    {
        sb.AppendFormat("&#{0};", (int)input[i]);
    }

    strXmlText = sb.ToString();
    sb.Clear();
    sb = null;

    return strXmlText;
} // End Function SpecialXmlEscape

XML 1.0:

public static string Base64Encode(string plainText)
{
    var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
    return System.Convert.ToBase64String(plainTextBytes);
}

public static string Base64Decode(string base64EncodedData)
{
    var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
    return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
3
Stefan Steiger

サードパーティのライブラリ( Newtonsoft.Json )を代替として使用する:

public static string XmlEncode(string unescaped)
{
    if (unescaped == null) return null;
    return JsonConvert.SerializeObject(unescaped); ;
}

public static string XmlDecode(string escaped)
{
    if (escaped == null) return null;
    return JsonConvert.DeserializeObject(escaped, typeof(string)).ToString();
}

例:

a<b <==> "a&lt;b"

<foo></foo> <==> "foo&gt;&lt;/foo&gt;"

2

次の関数が作業を行います。 XmlDocumentをテストしませんでしたが、これははるかに高速だと思います。

public static string XmlEncode(string value)
{
    System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings 
    {
        ConformanceLevel = System.Xml.ConformanceLevel.Fragment
    };

    StringBuilder builder = new StringBuilder();

    using (var writer = System.Xml.XmlWriter.Create(builder, settings))
    {
        writer.WriteString(value);
    }

    return builder.ToString();
}

public static string XmlDecode(string xmlEncodedValue)
{
    System.Xml.XmlReaderSettings settings = new System.Xml.XmlReaderSettings
    {
        ConformanceLevel = System.Xml.ConformanceLevel.Fragment
    };

    using (var stringReader = new System.IO.StringReader(xmlEncodedValue))
    {
        using (var xmlReader = System.Xml.XmlReader.Create(stringReader, settings))
        {
            xmlReader.Read();
            return xmlReader.Value;
        }
    }
}
2

タグを返さない:というジョン・スキートの答えに基づく別の見解

void Main()
{
    XmlString("Brackets & stuff <> and \"quotes\"").Dump();
}

public string XmlString(string text)
{
    return new XElement("t", text).LastNode.ToString();
} 

これは、渡された値のみをXMLエンコード形式で返します。

Brackets &amp; stuff &lt;&gt; and "quotes"
2
Rick Strahl