XML'e dize çıkışı


92

XML öğesinin içeriğini doldurmak için kullanılabilecek, bir dizeden kaçmak ve bu dizeyi kaldırmak için kullanılabilecek herhangi bir C # işlevi var mı?

VSTS 2008 + C # + .Net 3.0 kullanıyorum.

DÜZENLEME 1: Basit ve kısa XML dosyasını birleştiriyorum ve serileştirme kullanmıyorum, bu yüzden elle XML karakterinden açıkça kaçmam gerekiyor, örneğin a<biçine koymam gerekiyor <foo></foo>, bu yüzden dizeden kaçmalı a<bve foo öğesine koymalıyım.



15
new XText(unescaped).ToString()
Aklıma gelen

3
Buna tökezleyen başka biri için, bunu en iyi cevap olarak buldum: stackoverflow.com/a/5304827/1224069
Philip Pittle

Yanıtlar:


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
Öğeyi belgeye eklemenize bile gerek yoktur. Ancak, ben hala en iyi ilk etapta bunu yapmak için denemek için söyleyebilirim - George ... elle şeyler yaparak kendisi için çalışmalarını yapıyor gibi geliyor
Jon Skeet

15
Bu yanıtı gerçekten beğenmedim çünkü çok ağır. XmlDocument, gerçek işi yapmak için XmlReader / XmlWriter'ı kullanacak, öyleyse neden takipte kalmayasınız ve bu ağır DOM'dan kaçınmayasınız?
Steven Sudit

7
@Will, OP, özniteliğe değil bir XML öğesine yerleştirilebilecek bir metinden kaçacak bir işlev istedi . XML öğelerine yerleştirilebildikleri için işlevim tek veya çift tırnaktan kaçmaz.
Darin Dimitrov

5
@darin iyi nokta ve vurgulanması gereken bir nokta. Bu görüşmenin sonucundan memnunum ve çekincelerimi geri çekiyorum. İyi günler efendim.

1
Acaba HttpUtility.HtmlEncodedan System.Webgüvenle kullanılabilir?
Pooven


38

DÜZENLEME: "Basit ve kısa XML dosyasını birleştiriyorum ve serileştirme kullanmıyorum, bu yüzden XML karakterinden elle açıkça çıkmam gerekiyor" diyorsunuz.

Bunu elle yapmamanızı şiddetle tavsiye ederim. Her şeyi sizin yerinize yapmak için XML API'lerini kullanın - orijinal dosyaları okuyun, ikisini tek bir belgede birleştirin (muhtemelen kullanmak istersiniz XmlDocument.ImportNode) ve ardından tekrar yazın. Kendi XML ayrıştırıcılarınızı / biçimlendiricilerinizi yazmak istemezsiniz. Serileştirme burada biraz önemsizdir.

Bize tam olarak ne yapmaya çalıştığınıza dair kısa ama eksiksiz bir örnek verebilirseniz, muhtemelen ilk başta kaçmak konusunda endişelenmekten kaçınmanıza yardımcı olabiliriz.


Orijinal cevap

Ne demek istediğiniz tam olarak belli değil, ancak normalde XML API'leri bunu sizin için yapar. Metni bir düğümde ayarlarsınız ve ihtiyaç duyduğu her şeyden otomatik olarak çıkacaktır. Örneğin:

LINQ to XML örneği:

using System;
using System.Xml.Linq;

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

        Console.WriteLine(element);
    }
}

DOM örneği:

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

Her iki örnekten de çıktı:

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

Elbette, XML'in kaçmasını istediğiniz varsayılır. Değilseniz, lütfen daha fazla ayrıntı gönderin.


Teşekkürler Jon, orijinal yazım EDIT 1 bölümüne daha fazla ayrıntı ekledim. Bana bazı yorum ve tavsiyeler verebilirseniz minnettarım. :-)
George2

"XML çıkışından sonra" - yani? Lütfen başka kelimelerle konuşabilir misiniz? İngilizce benim ana dilim değil. :-)
George2

Merhaba Jon, XML biçiminden normal dize biçimine kaçış nasıl kaldırılır, yani "Parantezler ve şeyler & lt; & gt;" girişinden "Parantezler & şeyler <>" çıktısını alıyoruz?
George2

2
@ George2: XElement'den Değeri veya XmlElement'ten InnerText'i istersiniz.
Jon Skeet

25

Tek satırlık kaçış için @sehe'ye teşekkürler:

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

Buna tek satırlık kaçışı da ekliyorum:

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

XText tırnak işaretlerinden kaçmaz.
Mert Gülsoy

9

George, çok basit. XML'i işlemek için her zaman XML API'lerini kullanın. Kaçan ve kaçan her şeyi sizin için yapıyorlar.

Dizeleri ekleyerek asla XML oluşturmayın.


Yaşanacak kelimeler. Kullanılabilir birçok XML API seçeneği vardır, ancak hepimizin hemfikir olması gereken tek şey, manuel dize birleştirmenin kabul edilemez olmasıdır.
Steven Sudit

Genel olarak buna katılıyorum, ancak el ile kaçmanın gerekli olabileceği çok nadir durumlar olabilir. Örneğin, Roslyn kullanarak XML belgeleri oluştururken.
svick

@svick: neden LINQ to XML kullanarak XML oluşturup sonra .ToString () kullanmıyorsunuz?
John Saunders

@JohnSaunders, çünkü Roslyn'in kendi XML sınıfları kümesi vardır XmlElementSyntax. Ve sizin de üretmeniz gerektiği gerçeği de karmaşıktır ///. Ve her satırı ayrı olarak oluşturamıyorum XObject, çünkü bu çok satırlı etiketler için çalışmaz.
svick

1
@svick: xml'yi tek bir satırda oluşturun, ///önüne yapıştırın ve sonra kodu yeniden biçimlendirin. Çok büyük bir mesele değil ve kesinlikle köşe dava. Kesinlikle gerekliyse, eminim istediğiniz şekilde XmlWritersatır sonları ve boşluklar yapmak için bir özel oluşturabilir , ancak ///yeni satırların önüne yerleştirebilirsiniz . Alternatif olarak, XML'i güzel bir şekilde yazdırmak için bir XSLT kullanın. Ancak her durumda, XML yine de bir XML API tarafından oluşturulmalıdır.
John Saunders

6

Ve bu soruyu bulduğumda benim gibi, XML düğüm adlarından kaçmak istiyorsanız, örneğin bir XML serileştirmeden okurken, en kolay yolu kullanın:

XmlConvert.EncodeName(string nameToEscape)

Ayrıca, XML öğeleri için boşluklardan ve geçerli olmayan karakterlerden de kaçar.

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


Bence, sorulara dayanarak, sadece iç metin istiyorlar. Çözümünüz işe yarayacak, ancak öğe ve öznitelik adları gibi şeyleri de ele almayı amaçladığı için biraz abartılı. \
Sean Duggan

1
Buraya düğüm adlarından kaçmaya çalıştım ve bulgularımın gelecekte herkese yardımcı olabileceğini düşündüm. Ayrıca "aşırılık" nedir anlamıyorum ama sorun değil. ;)
CharlieBrown

Oh, faydalı bilgi. :) Oy vermemenizin nedenlerinden birinin, insanların soruyu yanıtlamadığınızı düşünmelerinden kaynaklandığını belirttim.
Sean Duggan

Bağlantı, SecurityElement.Escape (String) için dokümanlara götürür, bu kasıtlı mıydı? XmlConvert.EncodeName (String) kendi sayfasına sahiptir. Bunun sorulmasının üzerinden birkaç yıl geçtiğini biliyorum, ama hangisini kullanacağımı nasıl bilebilirim? Aynı şeyi farklı şekillerde mi yapıyorlar?
micnil

@CharlieBrown: Belki de ondan ayrı bir soru oluşturup cevaplamak istersiniz, böylece insanlar onu daha iyi bulabilir. Gönderdiğiniz için teşekkürler!
Florian Straub

5

John Skeet'in yanıtını temel alan ve etiketleri döndürmeyen başka bir yaklaşım :

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

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

Bu, yalnızca XML olarak kodlanmış biçimde iletilen değeri döndürür:

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

4

UYARI: Necromancing

Yine de Darin Dimitrov'un yanıtı + System.Security.SecurityElement.Escape (string s) tamamlanmadı.

XML 1.1'de, en basit ve en güvenli yol HER ŞEYİ kodlamaktır. \ T için
gibi &#09;.
XML 1.0'da hiç desteklenmez.
XML 1.0 için olası bir geçici çözüm, karakter (ler) i içeren metni 64 tabanına kodlamaktır.

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

Öyleyse XML 1.1'de her şeyden nasıl kaçarsınız?
Philip Pittle

@Philip Pittle: SpecialXmlEscape'i görün
Stefan Steiger

3

Aşağıdaki fonksiyonlar işi yapacak. XmlDocument'e karşı test etmedim ama sanırım bu çok daha hızlı.

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

Alternatif olarak bir üçüncü taraf kitaplığı ( Newtonsoft.Json ) kullanma:

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

Misal:

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

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.