1

Possible Duplicate:
Amazon Marketplace XML parsing

I am new to parsing XML in C# and I have some data from Amazon MWS library that is displayed below. I need to parse out various ItemAttributes such as ItemDimensions. I am use to JSON responses so I am not sure how to apply this to XML. Would it be possible from someone to point me in the right direction? I have Googled XML Parsing with C# but not valuable results were found to help me complete my tasks.

<GetMatchingProductResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductResult ASIN="1430225491" status="Success">
  <Product>
    <Identifiers>
      <MarketplaceASIN>
        <MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
        <ASIN>1430225491</ASIN>
      </MarketplaceASIN>
    </Identifiers>
    <AttributeSets>
      <ns2:ItemAttributes xml:lang="en-US">
        <ns2:Author>Troelsen, Andrew</ns2:Author>
        <ns2:Binding>Paperback</ns2:Binding>
        <ns2:Brand>Apress</ns2:Brand>
        <ns2:Edition>5</ns2:Edition>
        <ns2:ItemDimensions>
          <ns2:Height Units="inches">9.21</ns2:Height>
          <ns2:Length Units="inches">7.48</ns2:Length>
          <ns2:Width Units="inches">2.52</ns2:Width>
          <ns2:Weight Units="pounds">5.80</ns2:Weight>
        </ns2:ItemDimensions>
        <ns2:IsAutographed>false</ns2:IsAutographed>
        <ns2:IsEligibleForTradeIn>true</ns2:IsEligibleForTradeIn>
        <ns2:IsMemorabilia>false</ns2:IsMemorabilia>
        <ns2:Label>Apress</ns2:Label>
        <ns2:Languages>
          <ns2:Language>
            <ns2:Name>english</ns2:Name>
            <ns2:Type>Unknown</ns2:Type>
          </ns2:Language>
          <ns2:Language>
            <ns2:Name>english</ns2:Name>
            <ns2:Type>Original Language</ns2:Type>
          </ns2:Language>
          <ns2:Language>
            <ns2:Name>english</ns2:Name>
            <ns2:Type>Published</ns2:Type>
          </ns2:Language>
        </ns2:Languages>
        <ns2:ListPrice>
          <ns2:Amount>59.99</ns2:Amount>
          <ns2:CurrencyCode>USD</ns2:CurrencyCode>
        </ns2:ListPrice>
        <ns2:Manufacturer>Apress</ns2:Manufacturer>
        <ns2:NumberOfItems>1</ns2:NumberOfItems>
        <ns2:NumberOfPages>1752</ns2:NumberOfPages>
        <ns2:PackageDimensions>
          <ns2:Height Units="inches">2.60</ns2:Height>
          <ns2:Length Units="inches">9.20</ns2:Length>
          <ns2:Width Units="inches">7.50</ns2:Width>
          <ns2:Weight Units="pounds">5.80</ns2:Weight>
        </ns2:PackageDimensions>
        <ns2:PartNumber>9781430225492</ns2:PartNumber>
        <ns2:ProductGroup>Book</ns2:ProductGroup>
        <ns2:ProductTypeName>ABIS_BOOK</ns2:ProductTypeName>
        <ns2:PublicationDate>2010-05-14</ns2:PublicationDate>
        <ns2:Publisher>Apress</ns2:Publisher>
        <ns2:SmallImage>
          <ns2:URL>http://ecx.images-amazon.com/images/I/51h9Sju5NKL._SL75_.jpg</ns2:URL>
          <ns2:Height Units="pixels">75</ns2:Height>
          <ns2:Width Units="pixels">61</ns2:Width>
        </ns2:SmallImage>
        <ns2:Studio>Apress</ns2:Studio>
        <ns2:Title>Pro C# 2010 and the .NET 4 Platform</ns2:Title>
      </ns2:ItemAttributes>
    </AttributeSets>
    <Relationships/>
    <SalesRankings>
      <SalesRank>
        <ProductCategoryId>book_display_on_website</ProductCategoryId>
        <Rank>43011</Rank>
      </SalesRank>
      <SalesRank>
        <ProductCategoryId>697342</ProductCategoryId>
        <Rank>36</Rank>
      </SalesRank>
      <SalesRank>
        <ProductCategoryId>3967</ProductCategoryId>
        <Rank>53</Rank>
      </SalesRank>
      <SalesRank>
        <ProductCategoryId>4013</ProductCategoryId>
        <Rank>83</Rank>
      </SalesRank>
    </SalesRankings>
  </Product>
</GetMatchingProductResult>
<ResponseMetadata>
  <RequestId>440cdde0-fa76-4c48-bdd1-d51a3b467823</RequestId>
</ResponseMetadata>
</GetMatchingProductResponse>
Community
  • 1
  • 1
Brandon Wilson
  • 4,462
  • 7
  • 60
  • 90
  • 7
    `not valuable results were found` [Are you serious???](http://msdn.microsoft.com/en-us/library/cc189056(v=vs.95).aspx) – user703016 Oct 23 '12 at 11:57
  • 1
    http://stackoverflow.com/questions/9535320/amazon-marketplace-xml-parsing or http://stackoverflow.com/questions/tagged/mws?sort=votes&pagesize=50 – JP Hellemons Oct 23 '12 at 11:59
  • 2
    @Cicada: This is most likely the worst resource you could have given the OP. Parsing XML with XmlReader is hard and errorprone and should only be used if you are working with *HUGE* XML files. In all other cases you should use [XDocument](http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.aspx) - or XmlDocument if you are still on a .NET version less than 3.5 – Daniel Hilgarth Oct 23 '12 at 12:02
  • @Cicada: If you don't intent to help the OP, you should not be posting at all. – Daniel Hilgarth Oct 23 '12 at 13:07

3 Answers3

4

I find "Linq To Xml" easier to use

var xDoc = XDocument.Parse(xml); //or XDocument.Load(filename);
XNamespace ns = "http://mws.amazonservices.com/schema/Products/2011-10-01";
var items = xDoc.Descendants(ns + "ItemAttributes")
                .Select(x => new
                {
                    Author = x.Element(ns + "Author").Value,
                    Brand = x.Element(ns + "Brand").Value,
                    Dimesions = x.Element(ns+"ItemDimensions").Descendants()
                                 .Select(dim=>new{
                                     Type = dim.Name.LocalName,
                                     Unit = dim.Attribute("Units").Value,
                                     Value = dim.Value
                                 })
                                .ToList()

                })
                .ToList();
L.B
  • 114,136
  • 19
  • 178
  • 224
2

You have not made clear exactly what you need from the XML, so I cannot give you an objective answer. I'll begin by stating that there are many different ways to parse XML using .Net (and C# in your case, albeit they are similar with VB and C#).

The first one that I would look into is actually modeling your XML Data into .Net objects, more specifically, POCOs. To that class model you could add attributes that would bind or relate them to the XML and then all you'd need to do is pass the data and the class to a XML deserializer.

Now, if you don't need to retrieve the whole object, you can either use XDocument or XmlDocument. The fun part of XDocument is that its syntax in LINQ friendly, so you can parse you XML very simply.

XmlDocument is more old-style sequential method invocation, but achieves the same thing.


Let me illustrate. Consider a simpler XML, for simplicity sake's:

<body> 
    <h1>This is a text.</h1>
    <p class="SomeClass">This is a paragraph</p>
</body>

(see what I did there? That HTML is a valid XML!)

I. Using A Deserializer:

First you model the classes:

[XmlRoot]
public class body
{
    [XmlElement]
    public h1 h1 { get; set; }

    [XmlElement]
    public p p { get; set; }
}

public class h1 
{
    [XmlText]
    public string innerXML { get; set; }
}

public class p 
{
    [XmlAttribute]
    public string id { get; set; }

    [XmlText]
    public string innerXML { get; set; }
}

Once you have your class model, you call the serializer.

void Main()
{
    string xml = 
@"<body> 
    <h1>This is a text.</h1>
    <p id=""SomeId"">This is a paragraph</p>
</body>";

    // Creates a stream that reads from the string
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(xml);
    writer.Flush();
    stream.Position = 0;

    // Check the classes below before proceding.

    XmlSerializer serializer = new XmlSerializer(typeof(body));
    var obj = (body)serializer.Deserialize(stream);


    // Check obj here with the debugger. All fields are filled.

}

II. Using XDocument

The example above makes for a very neat code, since you access everything typed. However, it demands a lot of setup work since you must model the classes. Maybe some simpler will suffice in your case. Let's say you want to get the attribute of the p element:

void Main()
{
    string xml = 
@"<body> 
    <h1>This is a text.</h1>
    <p id=""SomeId"">This is a paragraph</p>
</body>";

    // Creates a stream that reads from the string
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(xml);
    writer.Flush();
    stream.Position = 0;

    // Using XDocument

    var pAttrib = XDocument.Load(stream).Element("body").Element("p").Attribute("id").Value;
    Console.Writeline(pAttrib);
}

Simple, huh? You can do more complex stuff throwing LINQ there... Let's try to find the element with id named "SomeId":

void Main()
{
    string xml = 
@"<body> 
    <h1>This is a text.</h1>
    <p id=""SomeId"">This is a paragraph</p>
</body>";

    // Creates a stream that reads from the string
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(xml);
    writer.Flush();
    stream.Position = 0;

    // Using XDocument
    var doc = XDocument.Load(stream);

    var found = from body in doc.Elements("body")
                from elem in body.Elements()
                from attrib in elem.Attributes()
                where attrib.Name == "id" && attrib.Value == "SomeId"
                select elem;


    foreach (var e in found) Console.WriteLine(e);
}

Hope it helps.

Bruno Brant
  • 8,226
  • 7
  • 45
  • 90
2

You could reinvent the wheel, or you could use Amazon's wheel (see @George Duckett's answer for the direct link): Amazon Marketplace API

One option to address your question: if you want a tool that will enable you to work with your xml file, I would look at xsd.exe. MSDN for xsd.exe

This tool is able to generate classes from xml.

Otherwise, you can create a parser from the XDocument class that will allow you to use linq to build a parser such as @L.B noted in his post.

Community
  • 1
  • 1
Todd Richardson
  • 1,119
  • 1
  • 11
  • 22