簡體   English   中英

在 C# 中使用遞增的元素名稱反序列化 XML 響應

[英]Deserialize XML Response with Incremented Element Names in C#

我正在嘗試使用 ASP.NET C# 使用 3rd 方 API,該 API 返回結果,如下面的示例所示,並且我對子對象具有遞增名稱的事實感到困惑:

<Results>
    <Count>3</Count>
    <Result1>
        <Id>1</Id>
        <Property1>value</Property1>
        <Property2>value</Property2>
        ...
        <PropertyN>value</PropertyN>
    </Result1>
    <Result2>...properties...</Result2>
    <Result3>...properties...</Result3>
</Results>

我的 C# 類如下所述,通過一些研究,我假設我必須實現IXmlSerializable以某種方式處理這個:

public class Results : IXmlSerializable
{
    [XmlElement("Count")]
    public int Count { get; set; }

    public List<Result> ResultItems { get; set; }
}

這是 XML 的常見模式嗎?有人對如何序列化它有任何想法嗎? 我很少使用 XML(主要是 JSON),所以提前致謝。

使用 xml linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication42
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<Root>" +
                "<Results>" +
                    "<Count>3</Count>" +
                    "<Result1>...properties...</Result1>" +
                    "<Result2>...properties...</Result2>" +
                    "<Result3>...properties...</Result3>" +
                "</Results>" +
                "</Root>";

            XElement xResults = XElement.Parse(xml);

            Results results = xResults.Elements("Results").Select(x => new Results() {
                Count = (int)x.Element("Count"),
                ResultItems = x.Elements().Where(y => y.Name.LocalName.StartsWith("Result")).Select(y => (string)y).ToList()
            }).FirstOrDefault();

        }


    }
    public class Results
    {

        public int Count { get; set; }

        public List<string> ResultItems { get; set; }
    }

}

jdweng 的回答有效,對於那些可以選擇使用的人來說,應該接受它; 但是,我的問題是數據在一個更大的 XML 響應中,並且使用 xml 序列化程序而不是XElement可以很好地處理 95% 的字段(另外 5% 是我在問題中指定的部分),所以我不我不想放棄該代碼 - 相反,我想實現 IXmlSerializable 接口。

在撕掉了我的大部分頭發並從本文中獲得了一些幫助后,我終於想出了如何為我的情況實現IXmlSerializable ,我想為任何有類似問題的人發布答案,以及社區反饋,因為沒有似乎沒有關於堆棧溢出的任何內容:

public class Results : IXmlSerializable
{
    public int Count { get; set; }

    public List<Result> ResultItems { get; set; }

    public Results()
    {
        ResultItems = new List<Result>();
    }

    public XmlSchema GetSchema()
    {
        return (null);
    }

    public void ReadXml(XmlReader reader)
    {
        reader.ReadStartElement("Results");

        if(reader.Name == "Count")
        {
            Count = reader.ReadElementContentAsInt();
        }

        for (int i = Count; i > 0; i--)
        {
            var result = new Result();
            reader.ReadStartElement("Result" + i);

            result.Property1 = reader.ReadElementContentAsInt();
            result.Property2 = reader.ReadElementContentAsString();
            ...
            ...
            result.PropertyN = reader.ReadElementContentAsString();

            ResultItems.Add(result);
        }

        reader.ReadEndElement();
    }

    public void WriteXml(XmlWriter writer)
    {
        //I don't ever need to write this to XML, 
        //so I'm not going to implement this
        throw new NotImplementedException();
    }
}

首先,我調用reader.ReadToElement()並將元素名稱放在那里。 當 reader 被傳遞給ReadXml方法時,它位於請求結果的開頭,因此您需要將它傳遞到要序列化的對象的開頭。

然后,我讀取了名稱為 Count 的第一個元素。 我將值放在 Count 屬性中,然后遍歷所有結果。 需要注意的是,必須讀取結果對象的每個屬性,否則會出現異常。

最后,我閱讀了結束標簽並繼續我的生活。 請讓我知道您對此實現的看法,以及是否可以進行任何改進。

我無法弄清楚的一件事是,我有一個結果對象,而讀者有一個我想使用的方法: reader.ReadElementContentAs(typeof(Result), null) - 這樣做似乎比閱讀更好每個單獨的節點,就像我在我的實現中所做的那樣。 有誰知道這是怎么做到的嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM