1

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.

2
  • That does not seem possible. Commented Jul 10, 2016 at 20:40
  • Use composition or map it to a new class Commented Jul 10, 2016 at 20:44

2 Answers 2

1

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;
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunate that there doesn't seem to be an easily integrated solution to this. However, you did solve what I asked for - thanks!
1

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;}
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.