C# 如何使用XDocument往返实体化车厢?
假设我有以下XML文档:C# 如何使用XDocument往返实体化车厢?,c#,xml,linq-to-xml,C#,Xml,Linq To Xml,假设我有以下XML文档: <x xml:space='preserve'>
 </x> 我对W3C规范的理解是序列13 10。为了让序列13 10显示在我的解析树中,我必须包含字符实体&xdas(我认识到它们来自XML-1.1而不是XML-1.0,但它们澄清了XML-1.0中令人困惑的事情,但没有描述不同的行为) 如中所述,在执行任何其他处理之前,XML文档中的所有#xD字符都会被删除或替换为#xA字符。获取与此结果匹配的#xD字符的唯一方法是在实体值文
<x xml:space='preserve'>
</x>
我对W3C规范的理解是序列13 10
。为了让序列13 10
显示在我的解析树中,我必须包含字符实体&xd代码>as(我认识到它们来自XML-1.1而不是XML-1.0,但它们澄清了XML-1.0中令人困惑的事情,但没有描述不同的行为)
如中所述,在执行任何其他处理之前,XML文档中的所有#xD字符都会被删除或替换为#xA字符。获取与此结果匹配的#xD字符的唯一方法是在实体值文字中使用字符引用
有了它,这一切似乎都正常工作了。上述XML的文本内容是13 10
(而不是13 10
),这表明在解析之前,字符实体被保留,文本13 10
被替换为10
但是,我不知道如何让XDocument.ToString()
在序列化时对换行符进行实体化。也就是说,我希望(XDocument xd)=>XDocument.Parse($“{xd}”)
是一个无损函数。但如果我传入一个XDocument
实例,其中13 10
作为文本内容,则该函数将输出一个XDocument
实例,其中10
作为文本内容。请参见此演示:
var x = XDocument.Parse("<x xml:space='preserve'>
\r\n</x>");
present("content", x.Root.Value); // 13 10, expected
present("formatted", $"{x}"); // inside <x/>: 13 10, unexpected
x = XDocument.Parse($"{x}");
present("round tripped", x.Root.Value); // 10, unexpected
// Note that when formatting the version with just 10 in the value,
// we get Environment.NewLine in the formatted XML. So there is no
// way to differentiate between 10 and 13 10 with XDocument because
// it normalizes when serializing.
present("round tripped formatted", $"{x}"); // inside <x/>: 13 10, expected
void present(string label, string thing)
{
Console.WriteLine(label);
Console.WriteLine(thing);
Console.WriteLine(string.Join(" ", Encoding.UTF8.GetBytes(thing)));
Console.WriteLine();
}
var x=XDocument.Parse(
;\r\n”);
呈现(“内容”,x.Root.Value);//13月10日,预计
呈现(“格式化的“,$”{x}”);//内部:13-10,意外
x=XDocument.Parse($“{x}”);
当前(“往返”,x.Root.Value);//10,出乎意料
//请注意,在格式化值仅为10的版本时,
//我们在格式化的XML中获取Environment.NewLine。所以没有
//使用XDocument区分10和13 10的方法,因为
//它在序列化时正常化。
当前(“往返格式的“,$”{x}”);//内部:13-10,预计
存在无效(字符串标签、字符串对象)
{
控制台写入线(标签);
控制台。写线(东西);
WriteLine(string.Join(“,Encoding.UTF8.GetBytes(thing));
Console.WriteLine();
}
您可以看到,当序列化XDocument
时,它无法将回车符实体化为
代码>或
代码>。结果是它丢失了信息。如何安全地编码XDocument
,以免丢失我加载的原始文档中的任何内容,尤其是回车?对于往返XDocument
,不要使用,因为这是有损的。还要注意,即使您执行类似于xd.ToString(SaveOptions.DisableFormatting)
的操作,解析树中的任何回车符都将丢失
相反,请将正确配置的XmlWriter
与一起使用。如果使用XmlWriter
,则XmlWriter
将能够看到包含文本框的文档返回并正确编码。要指示它这样做,请设置为。您可能希望编写一个扩展方法,使其更易于重用
更改为使用此方法的演示如下:
var x = XDocument.Parse("<x xml:space='preserve'>
\r\n</x>");
present("content", x.Root.Value); // 13 10, expected
present("formatted", toString(x)); // inside <x/>: 38 35 120 68 59 10 ("
\n"), acceptable
x = XDocument.Parse(toString(x));
present("round tripped", x.Root.Value); // 13 10, expected
string toString(XDocument xd)
{
using var sw = new StringWriter();
using (var writer = XmlWriter.Create(sw, new XmlWriterSettings
{
NewLineHandling = NewLineHandling.Entitize,
}))
{
xd.WriteTo(writer);
}
return sw.ToString();
}
void present(string label, string thing)
{
Console.WriteLine(label);
Console.WriteLine(thing);
Console.WriteLine(string.Join(" ", Encoding.UTF8.GetBytes(thing)));
Console.WriteLine();
}
var x=XDocument.Parse(
;\r\n”);
呈现(“内容”,x.Root.Value);//13月10日,预计
呈现(“格式化”,toString(x));//内部:3835120685910(
;\n),可接受
x=XDocument.Parse(toString(x));
当前(“往返”,x.Root.Value);//13月10日,预计
字符串到字符串(XDocument xd)
{
使用var sw=new StringWriter();
使用(var writer=XmlWriter.Create(sw,新的XmlWriter设置
{
NewLineHandling=NewLineHandling.Entitize,
}))
{
xd.WriteTo(writer);
}
返回sw.ToString();
}
存在无效(字符串标签、字符串对象)
{
控制台写入线(标签);
控制台。写线(东西);
WriteLine(string.Join(“,Encoding.UTF8.GetBytes(thing));
Console.WriteLine();
}
根据网站礼仪,请您发表评论并说明理由?谢谢
var x = XDocument.Parse("<x xml:space='preserve'>
\r\n</x>");
present("content", x.Root.Value); // 13 10, expected
present("formatted", toString(x)); // inside <x/>: 38 35 120 68 59 10 ("
\n"), acceptable
x = XDocument.Parse(toString(x));
present("round tripped", x.Root.Value); // 13 10, expected
string toString(XDocument xd)
{
using var sw = new StringWriter();
using (var writer = XmlWriter.Create(sw, new XmlWriterSettings
{
NewLineHandling = NewLineHandling.Entitize,
}))
{
xd.WriteTo(writer);
}
return sw.ToString();
}
void present(string label, string thing)
{
Console.WriteLine(label);
Console.WriteLine(thing);
Console.WriteLine(string.Join(" ", Encoding.UTF8.GetBytes(thing)));
Console.WriteLine();
}