反序列化xml,其中string可能包含xml / html

时间:2016-10-17 15:18:33

标签: c# xml serialization deserialization

我正在尝试反序列化XML,其中元素可能包含html。这里有类似的东西:

<member name="P:System.Web.Optimization.Bundle.CdnPath">
    <summary>Gets or sets an alternate url for the bundle when it is stored in a content delivery network.</summary>
    <returns>An alternate url for the bundle <b>when it is stored</b> in a content delivery network.</returns>
</member>

我正在阅读和写作:

var serializer = new XmlSerializer(typeof(XmlResult));

using (var reader = new XmlTextReader(@"myxml.xml"))
    element = (XmlResult)serializer.Deserialize(reader);

using (var writer = new XmlTextWriter(@"myxml-Copy.xml", Encoding.UTF8))
    serializer.Serialize(writer, element);

反序列化后希望的行为是,它等于原始文件:

<returns>An alternate url for the bundle <b>when it is stored</b> in a content delivery network.</returns>

反序列化后的实际行为是

<returns>An alternate url for the bundle  in a content delivery network.</returns>

<b>...</b>中的全文已消失。 (因为它不是一个单独的对象,我知道) 知道怎么解决它,未定义的xml元素留在字符串中吗?或者,至少,我得到了全文? <b>对我来说并不重要。

3 个答案:

答案 0 :(得分:2)

假设我们有以下类:

[XmlRoot("member")]
public class Member
{
    [XmlElement("summary")]
    public string Summary { get; set; }
    [XmlIgnore]
    public string Returns { get; set; }
}

订阅XmlSerializerUnknownElement活动。

在事件处理程序中手动将我们的属性设置为数据。

private static void Serializer_UnknownElement(object sender, XmlElementEventArgs e)
{
    var element = (Member)e.ObjectBeingDeserialized;
    element.Returns = e.Element.InnerXml;
}

请注意,属性名称不应与xml节点名称匹配(区分大小写)。仅在此情况下触发事件。如果名称匹配,请使用XmlIgnore属性。

然后我们可以按如下方式反序列化数据:

var serializer = new XmlSerializer(typeof(Member));
serializer.UnknownElement += Serializer_UnknownElement;

Member element;
using (var reader = XmlReader.Create(@"test.txt"))
    element = (Member)serializer.Deserialize(reader);

但是,在这种情况下,序列化将与原始数据不同。

答案 1 :(得分:1)

XmlTextReader正在尝试解析HTML,就好像它是XML一样。但XML不允许您在另一个标记的内容中嵌套标记:

<parent_tag> tag text part 1 <nested_tag> illegal inside the content of parent_tag </nested_tag> tag text part 2 </parent_tag>

这是合法的,但对你没什么帮助

<parent_tag>
    <part_1> tag text part 1 </part_1>
    <nested_tag> now ok as in the hierarchy of parent_tag </nested_tag>
    <part_2> tag text part 2 </part_2>
</parent_tag>

@ jdweng建议将<b>替换为&lt;b&gt;,将</b>替换为&lt;/b&gt;是最简单的建议。您还必须处理所有其他嵌入式代码,例如<a><i><strong><em>等。

您也可以尝试使用它来处理任何HTML。请注意,您不能在HTML中的任何位置拥有CEND序列,即]]>

<member name="P:System.Web.Optimization.Bundle.CdnPath">
<![CDATA[
    <summary>Gets or sets an alternate url for the bundle when it is stored in a content delivery network.</summary>
    <returns>An alternate url for the bundle <b>when it is stored</b> in a content delivery network.</returns>
]]> 
</member>

CDATA部分告诉XML解析器将内容视为文字文本。 您可以预处理XML文件(作为纯文本),在所有<member> ... </member>标记内的任何文本周围插入CDATA和CEND标记。

答案 2 :(得分:0)

我们遇到了类似的问题。我认为我可以和XmlDocument对象一起使用,并利用带有少许xpath的SelectSingleNode或SelectNodes方法,从而能够提取所需的内容。

string sInformationSource = "a really long string with an xml which contains html to be converted into pdfs.";
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(sInformationSource)
XmlNodeList docsHtmlList = xdoc.SelecetNodes("pdf-generator/source-content/document/.");

之后,只需从每个XmlNode获取InnerText。