Link to home
Start Free TrialLog in
Avatar of Camillia
CamilliaFlag for United States of America

asked on

Find a node

I have a LINQ XElement like this. I want to find a node. I tried "nodes()" but i cant specify a node name:

 foreach (System.Xml.Linq.XElement xe in rule.CalculatorXml.Elements())
       {
          //if node is in ShippingMethod node...
                 
       }


-- I want to do replace this code with XElement
foreach (XmlNode methodNode in rule.SelectNodes("ShippingMethod"))
            {

             }
Avatar of abel
abel
Flag of Netherlands image

Do you mean to find a specific node, or any node, or a text node, or an attribute node? Or, to make things easier, can you give an example of the input XML and point to the node you want to "capture"?
Avatar of Camillia

ASKER

I thought I posted a sample XML, sorry. It's below.

I need to find "ShippingMethod" and the attribute "Code". and "Destination"

Original code is like this:
 foreach (XmlNode methodNode in rule.Configuration.SelectNodes("ShippingMethod"))
            {
                if (methodNode.Attributes["Code"] != null)
                {  ...
                   foreach (XmlNode destinationNode in methodNode.SelectNodes("Destination"))
                        {
<ScoreRule>
  <ShippingMethod Code="UPS1DA">
    <Destination Country="US" Area="IL" Value="0" />
   </ShippingMethod>
</ScoreRule>

Open in new window

See the code below. The variable "shipping' contains all shipping methods, and the variable destination contains all Destination elements. In the last two simple loops I extract some information of these elements and put them to txtResult, giving me:

ShippingMethod/@Code="UPS1DA"Destination/@Country="US"
as output.


string xmlString = @"<ScoreRule>
                      <ShippingMethod Code='UPS1DA'>
                        <Destination Country='US' Area='IL' Value='0' />
                       </ShippingMethod>
                    </ScoreRule>";
TextReader textRdr = new StringReader(xmlString);
XDocument xdoc = XDocument.Load(textRdr);
 
var shippings = from elem in xdoc.Descendants("ShippingMethod") select elem;
var destinations = from elem in xdoc.Descendants("Destination") select elem;
 
foreach (XElement x in shippings)
    txtResults.Text += x.Name + "/@Code = " + x.Attribute("Code") + "\r\n";
 
foreach (XElement x in destinations)
    txtResults.Text += x.Name + "/@Country = " + x.Attribute("Country") + "\r\n";

Open in new window

SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thanks , let me try.

Is there a way to cast XElement to XMLNode??
XmlNode is part of the DOM. XElement is part of LINQ. They cannot be cast to each other. It is usually best to either choose DOM or LINQ and not both (though you can mix and match).

To convert between the two you have to go all the way: serialize and load again.
To final result as Dictionary object as (Code, Destination, Country, Value)

Where your XML is :
<Rule>
      <ScoreRule>
        <ShippingMethod Code="UPS1DA">
            <Destination Country="US1" Area="IL1" Value="01" />
         </ShippingMethod>
      </ScoreRule>
      <ScoreRule>
        <ShippingMethod Code="UPS2DA">
            <Destination Country="US2" Area="IL2" Value="02" />
         </ShippingMethod>
      </ScoreRule>
      <ScoreRule>
        <ShippingMethod Code="UPS3DA">
            <Destination Country="US3" Area="IL3" Value="03" />
         </ShippingMethod>
      </ScoreRule>
      <ScoreRule>
        <ShippingMethod Code="UPS4DA">
            <Destination Country="US4" Area="IL4" Value="04" />
         </ShippingMethod>
      </ScoreRule>
</Rule>

May this will be helpful:


using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
 
namespace xml_Test
{
    class Program
    {
        private static Dictionary<string, string> Values    ;
 
        static void Main()
        {
      
            XDocument xdoc = XDocument.Load(@"C:\test.xml");
 
            List<XAttribute> attributes = (from c in xdoc.Descendants("ShippingMethod") select c.Attribute("Code")).ToList();
            var list = (from c in xdoc.Descendants("Destination")
                        select new
                                   { 
                                       Country = c.Attribute("Country"),
                                       Area = c.Attribute("Area"),
                                       Value = c.Attribute("Value")
                                   }).ToList();
 
 
            var finalresult = new List<Dictionary<string, string>>();
            for (int i = 0; i < attributes.Count; i++)
            {
                Values = new Dictionary<string, string>
                             {
                                 {"Shipping Method", attributes[i].Value},
                                 {"country", list[1].Country.Value},
                                 {"Area", list[1].Area.Value},
                                 {"Value", list[1].Value.Value}
                             };
                finalresult.Add(Values);
            }
        }
    }
}

Open in new window

Other way Try this :
 var results = (from item in xdoc.Descendants("ShippingMethod") 
                          select new
                                     {
                                         ShippingMethodCode = item.Attribute("Code").Value, 
                                         Country = item.Element("Destination").Attribute("Country").Value, 
                                         Area = item.Element("Destination").Attribute("Area").Value,
                                         Val = item.Element("Destination").Attribute("Value").Value,
                                     }).ToList();

Open in new window

thanks sree_ven. will look at both solutions.
hey, don't forget mine, you have three now ;D
yes, abel...do you ever sleep? :)
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
> yes, abel...do you ever sleep? :)

haha, think we are in different timezones, but sleeping... I can do that at the end of my life more then enough :)

Funny, before posting my attempt at a solution, I tried the approach of naspinski, but didn't get it to work, because I was selecting the attributes list and trying to loop over them again (should also be possible). But this looks very nice, naspinski (though it depends whether you can consider it simpler).
You guys are great. Thanks. Let me look at all this and try them.

>> but sleeping... I can do that at the end of my life more then enough :)
I have to quote you on this :)

Kamila.