字符串转义为XML

Geo*_*ge2 89 .net c# xml escaping visual-studio-2008

是否有任何C#函数可用于转义和取消转义字符串,可用于填充XML元素的内容?

我使用的是VSTS 2008 + C#+ .Net 3.0.

编辑1:我是串联简单和短期的XML文件,我不使用序列化,所以我需要手动明确转义XML字符,例如,我需要把a<b<foo></foo>,所以我需要逃避串a<b并付诸元素富.

Dan*_*olt 120

SecurityElement.Escape(string s)

  • 你怎么逃脱? (15认同)
  • 与选定的答案不同,这个答案逃脱了引用. (7认同)
  • 此答案似乎不适用于 等无效字符 (2认同)
  • 这个答案是不完整的。它只回答了一半的问题。 (2认同)
  • 解开: text = System.Security.SecurityElement.FromString(xmlContent).Text; (2认同)

Dar*_*rov 72

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我真的不喜欢这个答案,因为它太重了.XmlDocument将使用XmlReader/XmlWriter来完成真正的工作,那么为什么不切入追逐并避免那个沉重的DOM呢? (13认同)
  • @Will,OP要求一个函数将转义一个文本,该文本可以放在XML**元素**而不是属性中.我的函数不会转义单引号或双引号,因为它们可以放在XML元素中. (6认同)
  • 您甚至不需要将元素附加到文档中.但是,我仍然会说最好不要首先尝试这样做 - 听起来乔治正在通过手工做事为自己工作...... (5认同)
  • @darin好点,应该强调一点.我对这次谈话的结果感到满意,并撤回了我的保留意见.美好的一天,先生. (5认同)
  • @William `;` 和 `=` 不是 XML 中需要转义的字符。 (2认同)

Jon*_*eet 37

编辑:你说"我连接简单和短的XML文件,我不使用序列化,所以我需要手动显式转义XML字符".

强烈建议你不要手工做.使用XML API为您完成所有操作 - 读入原始文件,将两者合并为一个文档,但需要(您可能想要使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

两个例子的输出:

<tag>Brackets &amp; stuff &lt;&gt;</tag>
Run Code Online (Sandbox Code Playgroud)

当然,这是假设你想要XML转义.如果您不是,请发布更多详细信息.

  • @ George2:您向XElement询问其值,或者向XmlElement询问其InnerText。 (2认同)

Kei*_*son 24

感谢@sehe的单线逃生:

var escaped = new System.Xml.Linq.XText(unescaped).ToString();
Run Code Online (Sandbox Code Playgroud)

我添加了单行un-escape:

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

  • 这似乎没有正确处理引号``` (3认同)

Cha*_*own 9

如果你想,像我发现这个问题时一样,转义 XML 节点名称,例如从 XML 序列化读取时,使用最简单的方法:

XmlConvert.EncodeName(string nameToEscape)
Run Code Online (Sandbox Code Playgroud)

它还将为 XML 元素转义空格和任何无效字符。

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


Joh*_*ers 8

乔治,很简单.始终使用XML API来处理XML.他们为你做所有的逃避和失败.

永远不要通过附加字符串来创建XML.


Ric*_*ahl 7

另一种基于 John Skeet 的答案的方法,该答案不返回标签

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

public string XmlString(string text)
{
    return new XElement("t", text).LastNode.ToString();
} 
Run Code Online (Sandbox Code Playgroud)

这仅以 XML 编码格式返回传入的值:

Brackets &amp; stuff &lt;&gt; and "quotes"
Run Code Online (Sandbox Code Playgroud)


Ste*_*ger 5

警告:死灵法术

Darin Dimitrov 的回答 + System.Security.SecurityElement.Escape(string s) 仍然不完整。

在 XML 1.1 中,最简单和最安全的方法是对所有内容进行编码。
就像&#09;\t。
XML 1.0 根本不支持它。
对于 XML 1.0,一种可能的解决方法是对包含字符的文本进行 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
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)