簡體   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