-1

I know this is a repeated question over SO, but I those answers haven't really helped out. I am trying to get details of a book using Classify API with C#. It gives an XML output like:

<classify xmlns="http://classify.oclc.org">
    <response code="2"/>
    <!--
        Classify is a product of OCLC Online Computer Library Center: http://classify.oclc.org
    -->
    <work author="Coelho, Paulo | Clarke, Alan [Author; Translator] | Sampere, Daniel, 1985- [Illustrator; Draftsman] | Lemmens, Harrie, 1953- [Translator] | Smith, James Noel | Ruiz, Derek, 1980- [Adapter]" editions="176" format="Book" holdings="7530" itemtype="itemtype-book" pswid="1151562357" title="The alchemist">123115868</work>
    <authors>
        <author lc="n94113544" viaf="65709090">Clarke, Alan [Author; Translator]</author>
        <author lc="no2005013941" viaf="12032914">Lemmens, Harrie, 1953- [Translator]</author>
        <author lc="no2010190009" viaf="160023476">Sampere, Daniel, 1985- [Illustrator; Draftsman]</author>
        <author lc="n86099875" viaf="52700">Coelho, Paulo</author>
    </authors>
    <orderBy>hold desc</orderBy>
    <input type="stdnbr">9780754073963</input>
    <!-- Snip -->
</classify>

I have worked with XML but in PHP, not C# so I am new to it and the tutorials regarding this everywhere tell different things making me confused about what to do and how to do it. I simply want these things from the XML:

  • Title Of the Book ( in Work Element )
  • Authors of Book ( in Work Element )
  • ISBN of the Book ( in Input Element - type stdnbr )
  • Most Popular DDC ( in recommendations > ddc > mostPopular - attribute [nsfa] )

But with what the examples I have seen over here and on other forums I get NullReferenceException.

Code:

PS: It's not homework.

public frmAddItem(string xml)
{
    InitializeComponent();
    string itemName = null, itemAuth = null, itemISBN = null;
    XDocument xdoc = new XDocument();
    xdoc = XDocument.Parse(xml);    
    string itemName = xdoc.Element("classify").Descendants("work").Where(s => s.Attributes() == "title");
    string itemAuth = xdoc.Element("classify").Descendants("work").Attributes("author").ToString();
    string itemISBN = xdoc.Element("classify").Descendants("input").ToString();
    txtTitle.Text = itemName;
    txtAuth.Text = itemAuth;
    txtISBN.Text = itemISBN;
    string itemDDC = xdoc.Element("ddc").Descendants("latestEdition").Attributes("sfa");
}

EDIT Duplicate: The link mentioned as duplicate is not same/similar to my XML string. It uses a different approach that didn't work as mentioned in the start of the question.

echo_salik
  • 842
  • 1
  • 18
  • 35

1 Answers1

3

Since your XML document has a namespace defined, the APIs require you to qualify your element names with namespaces. Your code is only using the "local" names. There are a couple ways to qualify them. An example is below which gets the 'title' attribute. It is simple to expand on it to get whatever other content/attributes you want.

using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

public class Program
{
    public static void Main(string[] args)
    {
        var doc = XDocument.Load("http://classify.oclc.org/classify2/Classify?stdnbr=9780754073963");
        var nsManager = new XmlNamespaceManager(new NameTable());
        nsManager.AddNamespace("c", "http://classify.oclc.org");

        var work = doc.XPathSelectElement("//c:work", nsManager);
        Console.WriteLine(work.Attribute("title").Value);

        var mostPopular = doc.XPathSelectElement("//c:ddc/c:mostPopular", nsManager);
        Console.WriteLine(mostPopular.Attribute("nsfa").Value);            
    }
}
Mike Zboray
  • 39,828
  • 3
  • 90
  • 122