在C#中将“&”替换为“&”。

10

我感觉很愚蠢地问这个问题。我看到很多其他类似的问题,但没有一个能够回答我的问题。

我正在为一个对语法非常挑剔的程序创建一个XML文件。不幸的是,我是从头开始创建XML文件的。也就是说,我在单独放置每一行(大量的file.WriteLine(String))。

我知道这很丑陋,但这是我让逻辑正确工作的唯一方法。

无论如何,我有几个字符串中带有“&”。

if (value.Contains("&"))
   {
      value.Replace("&", "&");
   }

似乎不起作用。value.Contains()似乎可以看到它,但是替换并没有生效。我正在使用C# .Net 2.0 sp2. VS 2005。

请帮帮我..这已经是漫长的一周了..


1
我理解你的痛苦。不久之前,我也不得不生成一些XML数据发送给第三方,他们竟然自己编写了XML解析器(令人发抖),当然他们没有支持某些关键特性,例如空格、注释、处理指令等等! - Christian Hayter
是的,我正在为另一个程序拼凑一个“答案”文件。这些答案文件是由他们自己的专有软件创建的。将所有正确的数据按正确顺序组合起来,然后以他们非常特定的xml格式输出是很棘手的。 - Ian Kremer
您还需要使用其XML字符实体等效项替换<,>,'"字符。 - David R Tribble
这是一堆涉及到TrimMakeUpper以及几乎所有其他字符串操作函数的重复问题。也许这些内容需要放入string-manipulation标签的维基中。 - Ben Voigt
@Ben Voigt - 抱歉,我现在知道这是一个重复问题。当时,我认为 & 是一种奇怪的转义字符,所以认为这个问题是独特的。请原谅这个重复的问题。 - Ian Kremer
12个回答

39

如果您真的想这么做,您必须将Replace的结果(该方法返回一个新字符串,因为字符串是不可变的)赋回给变量:

value = value.Replace("&", "&amp;");

我建议重新考虑你编写XML的方式。如果你切换到使用XmlTextWriter,它将处理所有的编码工作(不仅仅是&,还包括其他需要编码的字符):

using(var writer = new XmlTextWriter(@"C:\MyXmlFile.xml", null))
{
    writer.WriteStartElement("someString");
    writer.WriteText("This is < a > string & everything will get encoded");
    writer.WriteEndElement();
}

应该产生:

<someString>This is &lt; a &gt; string &amp; 
    everything will get encoded</someString>

哦,我的天啊..现在我感觉非常愚蠢..我应该去睡一会儿。谢谢。 - Ian Kremer
使用.Replace的问题在于文本同时包含正确的XML实体&和错误的& 如果您控制XML生成,则XmlTextWriter绝对是最好的选择。 如果您无法控制XML生成,则请参阅我的答案以获取更加安全的解决方案。 - Trygve

9
你应该使用类似于Linq to XML(XDocument等)的东西来解决它。我100%确定你可以不用所有的WriteLine ;)展示一下你的逻辑?
否则,你可以使用这个方法,它将是防弹的(而不是.Replace("&")):
var value = "hej&hej<some>";
value = new System.Xml.Linq.XText(value).ToString(); //hej&amp;hej&lt;some&gt;

这也会处理你必须转义的<

更新: 我查看了XText.ToString()的代码,它内部创建了一个XmlWriter+ StringWriter并使用XNode.WriteTo。这可能对于给定的应用程序来说有些过度,因此如果要转换多个字符串,则应使用XText.WriteTo。一种快速可靠的替代方法是System.Web.HttpUtility.HtmlEncode

更新 2: 我发现这个System.Security.SecurityElement.Escape(xml)可能是最快的,并确保最大兼容性(自.NET 1.0以来已经支持,不需要System.Web引用)。


我相信你是对的。生成的XML文档结构会根据我从另一个XML文档中提取的值类型而有很大变化。有点难以解释,但我会记下你建议的内容,这样一旦我度过了“现在就完成它”的阶段,我就可以让它看起来不那么丑陋。谢谢。 - Ian Kremer
虽然你错过了代码的实际问题,但我会因为你建议使用XText而给你一个+1。 - Yogesh
只是一条注释。我被困在使用 .Net 2.0 sp2 上。我是否正确地认为 Linq 是一个 >=3.0 的功能? - Ian Kremer
1
@Ian 在 .Net 2.0 中不存在该选项。你可以考虑使用 HtmlEncode 替代 :) 这个网站展示了几种选项:http://weblogs.sqlteam.com/mladenp/archive/2008/10/21/Different-ways-how-to-escape-an-XML-string-in-C.aspx - Lasse Espeholt
1
@lasseespeholt 是的,那可能是我最好的选择。比一个巨大的多替换语句要好得多。谢谢。 - Ian Kremer

3
您可以使用正则表达式仅替换节点值中的字符"&":
输入数据示例(字符串)
<select>
 <option id="11">Gigamaster&Minimaster</option>
 <option id="12">Black & White</option>
 <option id="13">Other</option>
</select>

使用正则表达式进行替换

 Regex rgx = new Regex(">(?<prefix>.*)&(?<sufix>.*)<");
 data = rgx.Replace(data, ">${prefix}&amp;${sufix}<");

 XmlDocument xmlDoc = new XmlDocument();
 xmlDoc.LoadXml(data);

结果数据

<select>
 <option id="11">Gigamaster&amp;MiniMaster</option>
 <option id="12">Black &amp; White</option>
 <option id="13">Other</option>
</select>

3
我显然来得太晚了,但正确答案是:
System.Text.RegularExpressions.Regex.Replace(input, "&(?!amp;)", "&amp;");

希望这能帮助到某些人!

这是我发现的唯一可行的解决方案。谢谢。 - Dave
如果您有其他的XML实体,例如',它将无法工作。在这种情况下,它将被替换为:&apos;。 - Trygve
@Trygve,这个问题特别涉及到&。 - Gonza Oviedo
1
@GonzaOviedo,没错,但是意识到并避免不必要的副作用非常重要。在我看来,处理所有可能情况总是一个好习惯。 - Trygve

3

1
请注意,这个类不在ClientProfile中。 - H H

1

你可以尝试:

value = value.Replace("&", "&amp;");

1

字符串是不可变的。你需要写成:

value = value.Replace("&", "&amp;");

请注意,如果您这样做并且您的字符串包含"&amp;",它将被更改为"&amp;amp;"

是的,我会确保在if语句中进行测试。谢谢。 - Ian Kremer
3
或者说是"&amp;",如果你正在学习XML教程的话,这可能是你想要的内容。 - Jeffrey L Whitledge

1
我已创建以下函数来对 & 和 ' 进行编码,而不会破坏已经编码的 & 或 ' 或 "


    public static string encodeSelectXMLCharacters(string xmlString)
    {
        string returnValue = Regex.Replace(xmlString, "&(?!quot;|apos;|amp;|lt;|gt;#x?.*?;)|'",
            delegate(Match m)
            {
                string encodedValue;
                switch (m.Value)
                {
                    case "&":
                        encodedValue = "&amp;";
                        break;
                    case "'":
                        encodedValue = "&apos;";
                        break;
                    default:
                        encodedValue = m.Value;
                        break;
                }

                return encodedValue;
            });
        return returnValue;
    }

我相信表达式中有一个小错误。结尾缺少一个 | :This works "&(?!quot;|apos;|amp;|lt;|gt;|#x?.*?;)|'" - juhariis

0

不确定这对任何人有用...我为此奋斗了一段时间...这里有一个辉煌的正则表达式,您可以使用它来修复所有链接、JavaScript和内容。我不得不处理大量的旧内容,没有人想要纠正。

将其添加到您的主页面、控件或重新编码的渲染覆盖中,以使字符串通过它运行。请不要因为我把它放错地方而攻击我:

// remove the & from href="blaw?a=b&b=c" and replace with &amp; 
//in urls - this corrects any unencoded & not just those in URL's
// this match will also ignore any matches it finds within <script> blocks AND
// it will also ignore the matches where the link includes a javascript command like
// <a href="javascript:alert{'& & &'}">blaw</a>
html = Regex.Replace(html, "&(?!(?<=(?<outerquote>[\"'])javascript:(?>(?!\\k<outerquote>|[>]).)*)\\k<outerquote>?)(?!(?:[a-zA-Z][a-zA-Z0-9]*|#\\d+);)(?!(?>(?:(?!<script|\\/script>).)*)\\/script>)", "&amp;", RegexOptions.Singleline | RegexOptions.IgnoreCase);

这是一个渲染页面的大致框架,但可以适应许多用途而不会使您的页面崩溃。


0

虽然现在很晚了,但我想分享我的解决方案,它处理了文档中同时存在不正确的xml字符实体&和有效的xml字符实体&以及其他xml字符实体的情况。

此解决方案仅适用于您无法控制xml生成的情况,通常是因为它来自某些外部来源。如果您可以控制xml生成,请使用@Justin Niessner建议的XmlTextWriter。

它也非常快速,并处理所有不同的xml字符实体/引用

预定义字符实体:

& quot;

& amp;

& apos;

& lt;

& gt;

数字字符实体/引用:

& #nnnn;

& #xhhhh;

PS!实体/引用后面的空格不应包含在内,我只是在这里添加它以避免在页面呈现中对其进行编码

代码

    public static string CleanXml(string text)
    {
        int length = text.Length;
        StringBuilder stringBuilder = new StringBuilder(length);

        for (int i = 0; i < length; ++i)
        {
            if (text[i] == '&')
            {
                var remaining = Math.Abs(length - i + 1);
                var subStrLength = Math.Min(remaining, 12);
                var subStr = text.Substring(i, subStrLength);
                var firstIndexOfSemiColon = subStr.IndexOf(';');
                if (firstIndexOfSemiColon > -1)
                    subStr = subStr.Substring(0, firstIndexOfSemiColon + 1);
                var matches = Regex.Matches(subStr, "&(?!quot;|apos;|amp;|lt;|gt;|#x?.*?;)|'");
                if (matches.Count > 0)
                    stringBuilder.Append("&amp;");
                else
                    stringBuilder.Append("&");
            }
            else if (XmlConvert.IsXmlChar(text[i]))
            {
                stringBuilder.Append(text[i]);
            }
            else if (i + 1 < length && XmlConvert.IsXmlSurrogatePair(text[i + 1], text[i]))
            {
                stringBuilder.Append(text[i]);
                stringBuilder.Append(text[i + 1]);
                ++i;
            }
        }

        return stringBuilder.ToString();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接