简体   繁体   中英

Parse XML with Child Nodes

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 ie 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".

You can try:

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

if(part != null)
{
   var values = part.Descendants("Values");
}

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.

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

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