20

我有一个包含 XML 的字符串,我只想将它解析为 Xelement,但它有一个 & 符号。我在用 HtmlDecode 解析它时仍然遇到问题。有什么建议么?

string test = " <MyXML><SubXML><XmlEntry Element="test" value="wow&" /></SubXML></MyXML>"; 

XElement.Parse(HttpUtility.HtmlDecode(test));

我还添加了这些方法来替换这些字符,但我仍然收到 XMLException。

string encodedXml = test.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("\"", "&quot;").Replace("'", "&apos;");
XElement myXML = XElement.Parse(encodedXml);

t 甚至尝试过:

string newContent=  SecurityElement.Escape(test);
XElement myXML = XElement.Parse(newContent);
4

9 回答 9

26

理想情况下,XML 在您的代码使用它之前被正确转义。如果这超出了您的控制范围,您可以编写一个正则表达式。不要使用 String.Replace 方法,除非您绝对确定这些值不包含其他转义项。

例如,明显不合需要的"wow&amp;".Replace("&", "&amp;")结果。wow&amp;amp;

Regex.Replace 可以为您提供更多控制以避免这种情况,并且可以编写为仅匹配不属于其他字符的“&”符号,例如&lt;,类似:

string result = Regex.Replace(test, "&(?!(amp|apos|quot|lt|gt);)", "&amp;");

上述工作,但不可否认,它没有涵盖以&符号开头的各种其他字符,例如&nbsp;列表可以增长。

更灵活的方法是解码 value 属性的内容,然后重新编码。如果您有value="&wow&amp;"解码过程将返回"&wow&",然后重新编码将返回"&amp;wow&amp;",这是可取的。要做到这一点,你可以使用这个:

string result = Regex.Replace(test, @"value=\""(.*?)\""", m => "value=\"" +
    HttpUtility.HtmlEncode(HttpUtility.HtmlDecode(m.Groups[1].Value)) +
    "\"");
var doc = XElement.Parse(result);

请记住,上述正则表达式仅针对 value 属性的内容。如果 XML 结构中的其他区域存在相同的问题,则可以对其进行调整以匹配它们并以类似的方式替换它们的内容。


编辑:更新的解决方案应该处理标签之间的内容以及双引号之间的任何内容。请务必彻底测试。尝试使用正则表达式操作 XML/HTML 标记是不利的,因为它容易出错且过于复杂。您的情况有些特殊,因为您需要先对其进行消毒才能使用它。

string pattern = "(?<start>>)(?<content>.+?(?<!>))(?<end><)|(?<start>\")(?<content>.+?)(?<end>\")";
string result = Regex.Replace(test, pattern, m =>
            m.Groups["start"].Value +
            HttpUtility.HtmlEncode(HttpUtility.HtmlDecode(m.Groups["content"].Value)) +
            m.Groups["end"].Value);
var doc = XElement.Parse(result);
于 2009-09-24T22:19:06.227 回答
14

您的字符串不包含有效的 XML,这就是问题所在。您需要将字符串更改为:

<MyXML><SubXML><XmlEntry Element="test" value="wow&amp;" /></SubXML></MyXML>"
于 2009-09-24T20:01:00.107 回答
3

HtmlEncode 不能解决问题,它可能会创建更多的 & 符号(例如,一个 ' 可能会变成 ",这是一个 Xml 实体引用,如下所示:

&amp;   & 
&apos;  ' 
&quot;  " 
&lt;    < 
&gt;    > 

但是你可能会得到像   这样的东西,这在 html 中很好,但在 Xml 中不行。因此,就像其他人所说的那样,首先通过确保不属于您的 XML 的实际标记的任何字符(也就是说,在您的 xml 中作为变量或文本的任何内容)并且出现在实体引用中的任何字符来更正 xml list 被翻译成它们对应的实体(所以 < 会变成 <)。如果包含非法字符的文本是 xml 节点内的文本,您可以采取简单的方法并用 CDATA 元素包围文本,但这不适用于属性。

于 2009-09-24T20:10:45.687 回答
1

与号使 XML 无效。这无法通过样式表修复,因此您需要使用其他工具或 VB/C#/PHP/Delphi/Lisp/Etc 中的代码编写代码。删除它或将其翻译成 &.

于 2009-09-24T20:00:24.450 回答
0

如果您的字符串不是有效的 XML,它将不会被解析。如果它本身包含一个 & 符号,则它不是有效的 XML。与 HTML 不同,XML 非常严格。

于 2009-09-24T20:00:07.273 回答
0

您应该“编码”而不是解码。但是调用 HttpUtility.HtmlEncode 对您没有帮助,因为它也会对您的“<”和“>”符号进行编码,并且您的字符串将不再是 XML。

我认为对于这种情况,最好的解决方案是将 '&' 替换为 '& amp;' (没有空格)

于 2009-09-24T20:01:07.537 回答
0

也许考虑编写自己的 XMLDocumentScanner。这就是NekoHTML正在做的事情,它能够忽略不用作实体引用的 & 符号。

于 2009-12-29T09:07:33.450 回答
0

Filip 的答案是正确的,但是您可以劫持System.Xml.XmlDocument该类来为您执行此操作,而无需全新的实用程序功能。

XmlDocument doc = new XmlDocument();
string xmlEscapedString = (doc.CreateTextNode("Unescaped '&' containing string that would have broken your xml")).OuterXml;
于 2019-08-23T22:48:23.317 回答
0

这是最简单也是最好的方法。适用于所有字符并允许为任何 Web 服务调用(即 SharePoint ASMX)解析 XML。

public string XmlEscape(string unescaped)
        {
            XmlDocument doc = new XmlDocument();
            var node = doc.CreateElement("root");
            node.InnerText = unescaped;
            return node.InnerXml;
        }
于 2019-01-15T12:53:51.067 回答