views:

159

answers:

4

I want by linq save my xml in csv and I have o problem.

This bracket are here beacuse without it this code is not displaying (why ? )

<results>
    <Countries country="Albania">
        <Regions region="Centralna Albania">
            <Provinces province="Durres i okolice">
                <Cities city="Durres" cityCode="2B66E0ACFAEF78734E3AF1194BFA6F8DEC4C5760">
                    <IndividualFlagsWithForObjects Status="1" />
                    <IndividualFlagsWithForObjects  Status="0" />
                    <IndividualFlagsWithForObjects magazyn="2" />
                </Cities>
            </Provinces>
        </Regions>
    </Countries>
    <Countries country="Albania">
        <Regions region="Centralna Albania">
            <Provinces province="Durres i okolice">
                <Cities city="Durres" cityCode="2B66E0ACFAEF78734E3AF1194BFA6F8DEC4C5760">
                    <IndividualFlagsWithForObjects storage="0" Status="1" /> 
                    <IndividualFlagsWithForObjects storage="1" Status="0" /> 
                    <IndividualFlagsWithForObjects storage="2" Status="1" /> 
                </Cities>
            </Provinces>
        </Regions>
    </Countries>
</results>

I must point one important thing: the parent node is but when I use it loaded.Descendants("results") it gives me nothing.

XDocument loaded = XDocument.Load(@"c:\citiesxml.xml");

// create a writer and open the file
TextWriter tw = new StreamWriter("c:\\XmltoCSV.txt");

// Query the data and write out a subset of contacts
var contacts = (from c in loaded.Descendants("Countries")
    select new
    {
        Country = (string)c.Attribute("ountry").Value,
        Region = (string)c.Element("Regions").Attribute("region").Value,
        Province= c.Element("Regions").Element("Provinces").Attribute("prowincja").Value,
        City= c.Element("Regions").Element("Provinces").Element("Cities").Attribute("city").Value,
        Kod = c.Element("Regions").Element("Provinces").Element("Cities").Attribute("cityCode").Value,
        IndywidualnaFlagaStatus = c.Element("Regions").Element("Provinces").Element("Cities").Element("IndividualFlagsWithForObjects").Attribute("Status"),
        IndywidualnaFlagaWartosc = c.Element("Regions").Element("Provinces").Element("Cities").Element("IndividualFlagsWithForObjects").Attribute("storage")
    }).ToList();

last problem:

 IndywidualnaFlagaWartosc = c.Element("Regions").Element("Provinces").Element("Cities").Element("IndividualFlagsWithForObjects").Attribute("storage")

gives me :

IndywidualnaFlagaWartosc = {storage="0"} (I see this while debugging)
+1  A: 

Yout element names don't match your xml snipped (all your elements in the snippet are singular and in your linq query they are plural (countries - country , regions - region etc).

 var contacts = (from c in loaded.Descendants("Countries")
                           select new
                           {
                               Country = c.Element("Countries").Value,
                               Region = c.Element("Regions").Value,
                               Province= c.Element("Provinces").Value,
                               City = c.Element("Cities").Value,
                               Hotel = c.Element("Hotels").Value
                           }).ToList();
FiveTools
+1  A: 

You're requesting the Element as object, and not it's value. Your code should be:

var contacts = (from c in loaded.Descendants("Countries")
               select new
               {
                   Country = c.Element("Country").Value,
                   Region = c.Element("region").Value,
                   Province= c.Element("province").Value,
                   City = c.Element("city").Value,
                   Hotel = c.Element("hotel").Value
               }).ToList();

But I'm not sure this gives any results as well if I look at your XML. I'm guessing this should give you the results you want:

var contacts = (from c in loaded.Descendants("Countries")
               select new
               {
                   Country = c.Attribute("country").Value,
                   Region = c.Descendants("Regions").FirstOrDefault().Attribute("region")Value,
                   Province= c.Descendants("Provinces").FirstOrDefault().Attribute("province").Value,
                   City = c.Descendants("Cities").FirstOrDefault().Attribute("city").Value,
                   Hotel = c.Descendants("Hotels").FirstOrDefault().Attribute("hotel").Value
               }).ToList();

Please note that this code is quite fragile, because if one of the decentant elements is missing, an Exception will occur. You should some fine-tuning yourself to get the results you want.

Prutswonder
+1  A: 

I'm sorry, this answer isn't complete. You don't get values in anything but Country with the code below, but it should be a good starting point, so try using c.Element() and you should be using c.Attribute() like so:

var contacts = (from c in loaded.Descendants("Countries")
    select new
    {
        Country = (string)c.Attribute("country"),
        Region = (string)c.Attribute("region"),
        Province = (string)c.Attribute("province"),
        City = (string)c.Attribute("city"),
        Hotel = (string)c.Attribute("hotel")
    }).ToList();
CubanX
+4  A: 
var contacts = (from c in loaded.Descendants("Countries")
                        select new
                        {
                            Country = (string)c.Attribute("Country").Value,
                            Region = (string)c.Element("Regions").Attribute("region").Value,
                            Province = (string)c.Element("Regions").Element("Provinces").Attribute("province").Value,
                            City = (string)c.Element("Regions").Element("Provinces").Element("Cities").Attribute("city").Value,
                            Hotel = (string)c.Element("Hotels").Attribute("hotel").Value
                        }).ToList();

Hotel is not in your xml anywhere so that will need to be adjusted. I would generally recommend that you pull each item once and check for nulls, instead of pulling Regions 3 times as I have done here.

Stephan
if the attribute is not set on the node, the result of c.Attribute() will be null, and calling .Value will throw exception. also casting to string is not necessary since the value is returned as string already.
Stephane
Men,thank you !I'm in yours debt .
@Stephane You are exactly right. As far as the null problem, I was just giving the quick solution. Obviously you would want to check for null first, but this gets the basic intention across. The string cast is there for my ease of reading. I like being able to easily see what type I'm dealing with in a select statement.
Stephan
I have still a problemwhen I read only Country and region is ok, but when i add Province I get Object reference not set to an instance of an object. Maybe because Provinces is not element of Country ??
Yes, I misread your xml. Provinces is a child of Regions so it should be c.Element("Regions").Element("Provinces").Attribute("province").ValueI will update to show that.
Stephan