String melarikan diri ke XML


92

Apakah ada fungsi C # yang dapat digunakan untuk keluar dan melepaskan string, yang dapat digunakan untuk mengisi konten elemen XML?

Saya menggunakan VSTS 2008 + C # + .Net 3.0.

EDIT 1: Saya concatenating sederhana dan file XML pendek dan saya tidak menggunakan serialisasi, jadi saya perlu secara eksplisit melarikan diri karakter XML dengan tangan, misalnya, saya harus menempatkan a<bke dalam <foo></foo>, jadi saya perlu melarikan diri tali a<bdan memasukkannya ke dalam elemen foo.



15
Terpendek yang dapat saya pikirkan:new XText(unescaped).ToString()
lihat

3
Bagi orang lain yang tersandung pada ini, saya telah menemukan ini sebagai jawaban terbaik: stackoverflow.com/a/5304827/1224069
Philip Pittle

Jawaban:


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

5
Anda bahkan tidak perlu menambahkan elemen ke dokumen. Namun, saya tetap akan mengatakan bahwa yang terbaik adalah tidak mencoba melakukan ini sejak awal - sepertinya George bekerja untuk dirinya sendiri dengan melakukan sesuatu dengan tangan ...
Jon Skeet

15
Saya sangat tidak menyukai jawaban ini karena terlalu berat. XmlDocument akan menggunakan XmlReader / XmlWriter untuk melakukan pekerjaan sebenarnya, jadi mengapa tidak langsung saja dan menghindari DOM yang berat itu?
Steven Sudit

7
@Apakah, OP meminta fungsi yang akan melarikan diri dari teks yang bisa dimasukkan ke dalam elemen XML dan bukan atribut. Fungsi saya tidak luput dari tanda kutip tunggal atau ganda karena dapat dimasukkan ke dalam elemen XML.
Darin Dimitrov

5
@darin bagus, dan salah satu yang harus ditekankan. Saya puas dengan hasil percakapan ini, dan menarik reservasi saya. Selamat siang, pak.

1
Saya ingin tahu apakah HttpUtility.HtmlEncodedari System.Webbisa digunakan dengan aman?
Pooven


38

EDIT: Anda mengatakan "Saya menggabungkan file XML sederhana dan pendek dan saya tidak menggunakan serialisasi, jadi saya harus secara eksplisit melepaskan karakter XML dengan tangan".

Saya sangat menyarankan Anda untuk tidak melakukannya dengan tangan. Gunakan API XML untuk melakukan semuanya untuk Anda - baca di file asli, gabungkan keduanya menjadi satu dokumen sesuka Anda (Anda mungkin ingin menggunakannya XmlDocument.ImportNode), lalu tulis lagi. Anda tidak ingin menulis pengurai / pemformatan XML Anda sendiri. Serialisasi agak tidak relevan di sini.

Jika Anda dapat memberi kami contoh singkat namun lengkap tentang apa yang Anda coba lakukan, kami mungkin dapat membantu Anda untuk menghindari kekhawatiran tentang melarikan diri sejak awal.


Jawaban asli

Tidak sepenuhnya jelas apa yang Anda maksud, tetapi biasanya XML API melakukan ini untuk Anda. Anda mengatur teks dalam sebuah node, dan itu akan secara otomatis melarikan diri dari apapun yang diperlukan. Sebagai contoh:

Contoh LINQ ke XML:

using System;
using System.Xml.Linq;

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

        Console.WriteLine(element);
    }
}

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

Keluaran dari kedua contoh:

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

Itu dengan asumsi Anda ingin XML melarikan diri, tentu saja. Jika tidak, harap posting detail selengkapnya.


Terima kasih Jon, saya telah memberikan detail lebih lanjut ke bagian EDIT 1 posting asli saya. Hargai jika Anda bisa memberi saya beberapa komentar dan nasihat. :-)
George2

"setelah XML melarikan diri" - maksud Anda? Bisakah Anda berbicara dengan kata lain? Bahasa Inggris bukan bahasa ibu saya. :-)
George2

Hai Jon, bagaimana cara melepaskan diri dari format XML ke format string normal, yaitu dari input "Brackets & amp; stuff & lt; & gt;", kami mendapatkan output "Brackets & stuff <>"?
George2

2
@ George2: Anda meminta XElement untuk Nilainya, atau XmlElement untuk InnerText-nya.
Jon Skeet

25

Terima kasih kepada @sehe untuk pelarian satu baris:

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

Saya menambahkan satu baris un-escape:

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

XText tidak luput dari tanda kutip.
Mert Gülsoy

9

George, itu sederhana. Selalu gunakan API XML untuk menangani XML. Mereka melakukan semua pelarian dan pelarian untuk Anda.

Jangan pernah membuat XML dengan menambahkan string.


Kata-kata untuk hidup. Ada banyak opsi API XML yang tersedia, tetapi satu hal yang harus kita sepakati bersama adalah bahwa penggabungan string manual tidak dapat diterima.
Steven Sudit

Meskipun secara umum saya setuju dengan ini, mungkin ada beberapa kasus yang sangat jarang di mana pelolosan manual mungkin diperlukan. Misalnya, saat membuat dokumentasi XML menggunakan Roslyn.
svick

@svick: mengapa tidak membuat XML menggunakan LINQ ke XML, lalu gunakan .ToString ()?
John Saunders

@JohnSaunders, karena Roslyn memiliki kumpulan kelas XML-nya sendiri, seperti XmlElementSyntax. Dan itu juga diperumit oleh fakta bahwa Anda perlu membuat ///juga. Dan saya tidak dapat membuat setiap baris sebagai terpisah XObject, karena itu tidak akan berfungsi untuk tag multiline.
svick

1
@svick: jadi buat xml, semua dalam satu baris, tempelkan ///di depannya, lalu format ulang kode. Bukan masalah besar, dan tentu saja kasus sudut. Jika benar-benar diperlukan, saya yakin Anda dapat membuat kebiasaan XmlWriteruntuk melakukan jeda baris dan spasi seperti yang Anda inginkan, tetapi menempatkannya ///di depan baris baru. Atau, gunakan XSLT untuk mencetak XML dengan cantik. Namun bagaimanapun, XML tetap harus dibuat oleh API XML.
John Saunders

6

Dan jika Anda ingin, seperti saya ketika saya menemukan pertanyaan ini, untuk keluar dari nama node XML, seperti misalnya saat membaca dari serialisasi XML, gunakan cara termudah:

XmlConvert.EncodeName(string nameToEscape)

Ini juga akan mengosongkan spasi dan karakter tidak valid untuk elemen XML.

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


Menurut saya, berdasarkan pertanyaan, mereka hanya menginginkan teks batin. Solusi Anda akan berfungsi, tetapi agak berlebihan karena dimaksudkan untuk menangani hal-hal seperti nama elemen dan atribut. \
Sean Duggan

1
Saya sampai di sini mencoba untuk melarikan diri dari nama node apa pun dan berpikir bahwa temuan saya dapat membantu siapa pun di masa depan. Saya juga tidak melihat apa yang "berlebihan" tapi tidak apa-apa. ;)
CharlieBrown

Oh, itu informasi yang berguna. :) Saya baru saja menyadari bahwa saya akan menunjukkan bahwa salah satu alasan Anda mungkin tidak mendapat suara positif adalah karena orang mungkin merasa Anda tidak menjawab pertanyaan yang ada.
Sean Duggan

Tautan mengarah ke dokumen untuk SecurityElement.Escape (String), apakah ini disengaja? XmlConvert.EncodeName (String) memiliki halamannya sendiri. Saya tahu sudah beberapa tahun sejak ini ditanyakan, tetapi bagaimana saya tahu mana yang harus digunakan? Bukankah mereka melakukan hal yang sama tetapi dengan cara yang berbeda?
micnil

@CharlieBrown: Mungkin Anda juga ingin membuat pertanyaan terpisah dan menjawabnya, sehingga orang dapat menemukannya dengan lebih baik. Terima kasih telah mempostingnya!
Florian Straub

5

Pengambilan lain berdasarkan jawaban John Skeet yang tidak mengembalikan tag :

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

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

Ini hanya mengembalikan nilai yang diteruskan, dalam format yang dikodekan XML:

Brackets &amp; stuff &lt;&gt; and "quotes"

4

PERINGATAN: Necromancing

Masih jawaban Darin Dimitrov + System.Security.SecurityElement.Escape (string s) belum lengkap.

Dalam XML 1.1, cara termudah dan teraman adalah dengan menyandikan SEMUANYA.
Suka &#09;untuk \ t.
Itu tidak didukung sama sekali dalam XML 1.0.
Untuk XML 1.0, satu solusi yang mungkin adalah dengan base-64 menyandikan teks yang berisi karakter (s).

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

Jadi di XML 1.1, bagaimana Anda bisa kabur dari semuanya?
Philip Pittle

@Philip Pittle: Lihat SpecialXmlEscape
Stefan Steiger

3

Fungsi berikut akan melakukan pekerjaannya. Tidak menguji XmlDocument, tapi saya rasa ini jauh lebih cepat.

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

3

Menggunakan perpustakaan pihak ketiga ( Newtonsoft.Json ) sebagai alternatif:

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

Contoh:

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

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.