c# - 我可以使用 WebUtility.HtmlDecode 解码 XML 吗?
问题描述
我有一个 XML 编码的属性值。这实际上来自处理指令。所以原始数据看起来像这样:
<root><?pi key="value" data="<foo attr="bar">Hello world</foo>" ?></root>
我可以这样解析它:
using System;
using System.Linq;
using System.Xml.Linq;
public class Program
{
private const string RawData = @"<root><?pi key=""value"" data=""<foo attr="bar">Hello world</foo>"" ?></root>";
public static void Main()
{
XDocument doc = GetXDocumentFromProcessingInstruction();
IEnumerable<XElement> fooElements = doc.Descendants("foo");
// ...
}
private static XProcessingInstruction LoadProcessingInstruction()
{
XDocument doc = XDocument.Parse(rawData);
return doc
.DescendantNodes()
.OfType<XProcessingInstruction>()
.First();
}
private static XDocument GetXDocumentFromProcessingInstruction()
{
XProcessingInstruction processingInstruction = LoadProcessingInstruction();
// QUESTION:
// Can there ever be a situation where HtmlDecode wouldn't decode the XML correctly?
string decodedXml = WebUtility.HtmlDecode(processingInstruction.Data);
// This works well, but it contains the attributes of the processing
// instruction as text.
string dummyXml = $"<dummy>{xml}</dummy>";
return XDocument.Parse(dummyXml);
}
据我所知,这绝对没问题。但我想知道是否存在一些可能失败的边缘情况,因为数据在 XML 和 HTML 中的编码方式不同。
有人有更多的见解吗?
编辑:对不起,我对 XProcessingInstruction.Data 做了一些不正确的假设,但上面的代码仍然可以正常工作,所以我的问题是存在的。尽管如此,我还是重写了我的代码并将所有内容包装在一个 XElement 中,这(当然)完全消除了这个问题:
private static XDocument GetXDocumentFromProcessingInstruction2()
{
XProcessingInstruction processingInstruction = LoadProcessingInstruction();
string encodedXml = string.Format("<dummy {0} />", processingInstruction.Data);
XElement element = XElement.Parse(encodedXml);
string parsedXml = element.Attribute("data").Value;
return XDocument.Parse(parsedXml);
}
所以这正是我需要的。但是由于 WebUtility.HtmlDecode 工作得很好,我仍然想知道是否存在第一种方法可能失败的情况。
解决方案
删除问号并在输入末尾添加正斜杠我得到了这个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input = "<pi data=\"<foo attr="bar">Hello world</foo>\" />";
XElement pi = XElement.Parse(input);
string data = (string)pi.Attribute("data");
XElement foo = XElement.Parse(data);
string attr = (string)foo.Attribute("attr");
string innertext = (string)foo;
}
}
}