-1

I have an XML file which returns a list of products with colors and inventory for each color. What is the best method to loop through this data only returning inventory by color for a specific product i.e. PL-0223?

Here is the data.

<Part fpartno="0019">
    <Color colorname="Nickel"> 
        <ValueAmt>
            <Values Qty= "12101" Date ="ATP" Type= "Avail"/>
            <Values Qty= "12101" Date= "Total" Type="Total"/> 
        </ValueAmt>
    </Color>
</Part>
<Part fpartno="0223">
    <Color colorname="White"> 
        <ValueAmt>
            <Values Qty= "0" Date ="ATP" Type= "Avail"/>
            <Values Qty= "0" Date= "Total" Type="Total"/> 
        </ValueAmt>
    </Color>
    <Color colorname="Yellow"> 
        <ValueAmt>
            <Values Qty= "0" Date ="ATP" Type= "Avail"/>
            <Values Qty= "0" Date= "Total" Type="Total"/> 
        </ValueAmt>
    </Color>
</Part>

I've seen examples using both Linq to SQL and XmlReader but I have not found a good solution to loop through SubTree's/Child Nodes.

Examples of what I've tried.

XmlReader Method. I can't seem to figure out how to get the sub elements.

using(XmlReader r = XmlReader.Create(URLString))
{
    while(r.Read())
    {
        if((r.NodeType == XmlNodeType.Element) && (r.Name == "Part"))
        {
            if(r.HasAttributes)
            {                    
                if(r.GetAttribute("fpartno") == "0019")
                {
                    using (XmlReader cr = r.ReadSubtree())
                    {
                        Console.WriteLine(cr.Name)
                    }
                }
            }
        }
    }
}

I've also tried XDoc

XDocument xdoc = XDocument.Load(URLString);
foreach (XElement element in xdoc.Descendants("Values"))
{
    Console.WriteLine(element);
} 

But can't seem to figure out how to only get colors for "0019".

Jason Miller
  • 253
  • 1
  • 3
  • 10
  • 1
    Please don't just ask us to solve the problem for you. Show us how _you_ tried to solve the problem yourself, then show us _exactly_ what the result was, and tell us why you feel it didn't work. See "[What Have You Tried?](http://whathaveyoutried.com/)" for an excellent article that you _really need to read_. – John Saunders Apr 14 '14 at 21:54
  • I've added edits. I'm new to XML parsing hence the lack of a detailed post hence the lack of down votes it appears to be receiving. – Jason Miller Apr 14 '14 at 22:05

3 Answers3

1

You can try:

var part = xdoc.Descendants("Parts")
             .FirstOrDefault(x => (string)x.Attribute("fpartno") == "0223");

if(part != null)
{
   var values = part.Descendants("Values");
}
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
0

This is the Raison d'être of XPath:

var doc = new System.Xml.XmlDocument();
doc.Load(URLString);

foreach(System.Xml.XmlNode node in 
   doc.SelectNodes("//Part[@fpartno='0223']/Color[@colorname='White']/ValueAmt/Values")
{
  Console.WriteLine(node.InnerXml);
}

Note that your sample data above is not a valid XML document - it's an Xml fragment. To use XPath on it, you'll need to wrap the data in a root node so that the resulting document has a single root (unless it already has a wrapper that you just didn't show). Working out the general case of how to construct the XPath query string is left as an exercise for the student.

Also note that XDocument doesn't support XPath - only the pre-LINQ XmlDocument class support XPath directly. You can mix XPath and XDocument, however, by using XDocument.CreateNavigator to create an XPathNavigator, which you can then query using XPath.

CarlDaniel
  • 333
  • 3
  • 16
0

Here's the solution I came up with.

string URLString = "http://example.com/test.xml";
XElement xelement = XElement.Load(URLString);
var part = from partno in xelement.Descendants("Part")
           where (string)partno.Attribute("fpartno") == "0019"
           select partno;

foreach (XElement xEle in part)
{
    Console.log(xEle.Element("Color").Attribute("colorname").Value);

    foreach (var node in xEle.Element("Color").Element("ValueAmt").Elements("Values"))
    {
        Console.log(node.Attribute("Qty").Value);
    }
}
Jason Miller
  • 253
  • 1
  • 3
  • 10