繁体   English   中英

C# XML 反序列化自关闭原始元素

[英]C# XML deserialize self closing raw element

我需要处理一些 XML 输入,在某些标签中有 HTML 代码。 对于这些标签,我希望原始内容稍后进行处理。 我遵循了这个答案并使用了在大多数情况下都可以正常工作的XmlElement 我面临的唯一问题是自动关闭标签。

[Serializable]
public class Root
{
    public XmlElement Description { get; set; }
    public string Name { get; set; }
}

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

var obj1 = serializer.Deserialize(new StringReader(@"<Root><Description><p>test</p></Description><Name>Test</Name></Root>"));
// Description: "Element, Name=\"p\""
// Name: "Test"

var obj2 = serializer.Deserialize(new StringReader(@"<Root><Description></Description><Name>Test</Name></Root>"));
// Description: null
// Name: "Test"

var obj3 = serializer.Deserialize(new StringReader(@"<Root><Description/><Name>Test</Name></Root>"));
// Description: "Element, Name=\"Name\""
// Name: null

obj1obj2没问题( obj2.Description == ""会更好)但是在obj3Description成员是贪婪的并且包含Name部分。

这个问题有解决方法吗?

一种可能的解决方法是为Description属性声明自定义 class,使用[XmlAnyElement] 属性匹配元素内的任何内容:

public class Root
{
    public Description Description { get; set; }

    public string Name { get; set; }
}


public class Description
{
    [XmlAnyElement]
    public List<XmlElement> Content { get; set; }
}

唯一的缺点是这不适用于混合内容。 换句话说,这将很好地反序列化:

<Description><p>test</p></Description>

但这不会,仅反序列化<span>

<Description>some <span>other</span> text</Description>

如果您需要混合内容,请在Description class 上实施IXmlSerializable

但是,它确实适用于<Description/> 话虽如此,我同意@MarcGravell 的观点,即它是XmlSerializer中的一个错误,应该报告。

按照建议,我报告了这个问题

我现在使用此代码来解决此问题:

using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
                    
public class Program
{
    public static void Main()
    {
        var serializer = new XmlSerializer(typeof(Root));

        var obj1 = serializer.Deserialize(new StringReader(@"<Root><Description><p>test</p></Description><Name>Test</Name></Root>"));
        Console.WriteLine(obj1); // Description: <p>test</p> / Name: Test

        var obj2 = serializer.Deserialize(new StringReader(@"<Root><Description></Description><Name>Test</Name></Root>"));
        Console.WriteLine(obj2); // Description:  / Name: Test

        var obj3 = serializer.Deserialize(new StringReader(@"<Root><Description/><Name>Test</Name></Root>"));
        Console.WriteLine(obj3); // Description:  / Name: Test
    }

    public class Root
    {
        public HtmlElement Description { get; set; }
        public string Name { get; set; }
        
        public override string ToString() => $"Description: {Description.Content} / Name: {Name}";
    }
    
    public class HtmlElement : IXmlSerializable
    {
        public string Content { get; set; } = "";

        public XmlSchema GetSchema() => null;

        public void ReadXml(XmlReader reader)
        {
            reader.MoveToContent();

            if (!reader.IsEmptyElement && reader is XmlTextReader xtr)
            {
                Content = xtr.ReadInnerXml();
            }
        }

        public void WriteXml(XmlWriter writer) => throw new NotImplementedException();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM