简体   繁体   中英

Deserializing array of XML with attributes C#

I'm using the NPR XML API with C#. I have a story XML object, with three link nodes, with the only difference being the type attribute.

<story id="485432424">
  <link type="html">http://www.npr.org/2016/07/10/485432424/with-administrative-corruption-in-afghanistan-u-s-troops-presence-won-t-make-any?ft=nprml&amp;f=1149</link>
  <link type="api">http://api.npr.org/query?id=485432424&amp;apiKey=MDIxNjY4ODAwMDE0NTAxMjAwODQ4ZTA1Nw000</link>
  <link type="short">http://n.pr/29EFodu</link>

I know I could deserialize these links into an array, and call something like story.Links[0] to get the html link version, but that seems like poor design. What would be preferable is to have an HTML, API, and Short property directly in my Story object, so I could access it like this: story.Link.HTML or story.Link.API .

Is there any way to achieve this with the Microsoft XML library? I haven't found any decorator that would do something like this, unfortunately.

This is kind of an old school way to do it, but I'd do something like the below and just create my own class structure.

class Program
{
    static void Main(string[] args)
    {
        string sXml = @"<story id=""485432424"">
                <link type=""html"">http://www.npr.org/2016/07/10/485432424/with-administrative-corruption-in-afghanistan-u-s-troops-presence-won-t-make-any?ft=nprml&amp;f=1149</link>
                <link type=""api"">http://api.npr.org/query?id=485432424&amp;apiKey=MDIxNjY4ODAwMDE0NTAxMjAwODQ4ZTA1Nw000</link>
                <link type=""short"">http://n.pr/29EFodu</link>
            </story>";

        System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
        doc.LoadXml(sXml);

        Story story = new Story(doc.DocumentElement);

        Console.Write(story.ToString());
        Console.ReadLine();
    }
}

class Story
{
    public Link Link { get; set; }
    public Story(System.Xml.XmlNode nStory)
    {
        this.Link = new Link();
        foreach (System.Xml.XmlNode nLink in nStory.ChildNodes)
        {
            if (nLink.NodeType == System.Xml.XmlNodeType.Element)
            {
                this.Link.AddLink(nLink);
            }
        }
    }
    public override string ToString()
    {
        return new StringBuilder().Append(
            "Html: ").Append(this.Link.Html).Append(Environment.NewLine).Append(
            "Api: ").Append(this.Link.Api).Append(Environment.NewLine).Append(
            "Short: ").Append(this.Link.Short).Append(Environment.NewLine).ToString();
    }
}
class Link
{
    public string Html { get; set; }
    public string Api { get; set; }
    public string Short { get; set; }

    public Link()
    {
    }
    public void AddLink(System.Xml.XmlNode nLink)
    {
        switch (nLink.Attributes["type"].Value)
        {
            case "html":
                Html = nLink.InnerText;
                break;
            case "api":
                Api = nLink.InnerText;
                break;
            case "short":
                Short = nLink.InnerText;
                break;
        }
    }
}

You could use XDocument :

void Main()
{
    var xml = @"<story id=""485432424"">
      <link type=""html"">http://www.npr.org/2016/07/10/485432424/with-administrative-corruption-in-afghanistan-u-s-troops-presence-won-t-make-any?ft=nprml&amp;f=1149</link>
      <link type=""api"">http://api.npr.org/query?id=485432424&amp;apiKey=MDIxNjY4ODAwMDE0NTAxMjAwODQ4ZTA1Nw000</link>
      <link type=""short"">http://n.pr/29EFodu</link>
      </story>";

    using (var reader = new StringReader(xml))
    {
        var stories = new List<Story>();
        var xDoc = XDocument.Load(reader);
        foreach (var storyElement in xDoc.Elements("story"))
        {
            var story = new Story();
            foreach (var linkElement in storyElement.Elements("link"))
            {
                var value = linkElement.Attribute("type").Value;
                if (value == "html")
                    story.Html = linkElement.Value;
                else if (value == "api")
                    story.Api = linkElement.Value;
                else if (value == "short")
                    story.Short = linkElement.Value;
            }
            stories.Add(story);
        }

        // process stories;
    }
}

public class Story
{
    public string Html { get; set; }
    public string Api { get; set; }
    public string Short { get; set;}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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