1

I have following xml file:

<os:tax>
     <os:cat name="abc" id="1">
         <os:subcat name="bcd" id="11">
             <os:t name="def" id="111">
                 <os:cut name="hello" id="161" cutURL="/abc/a.html"/>
                 <os:cut name="hello2" id="162" cutURL="/abc1/a1.html"/>
                 <os:cut name="hello3" id="163" cutURL="/abc4/a3.html"/>
             </os:t>
         </os:subcat>
     </os:cat>
     <os:cat name="def" id="2">
         <os:subcat name="bcd" id="22">
             <os:t name="def" id="222">
                 <os:cut name="hello" id="171" cutURL="/abcs/a.html"/>
                 <os:cut name="hello2" id="172" cutURL="/abcs1/a1.html"/>
                 <os:cut name="hello3" id="173" cutURL="/abcs4/a3.html"/>
             </os:t>
         </os:subcat>
     </os:cat>
 </os:tax> 

Its a bigger file with lot of os:cat under it. I need to get string value for: os:cat -> id , name os:subcat -> id, name os: t -> id, name os: cut -> id, name, cutURL

I have this so far:

XmlNodeList tax = xmlDoc.GetElementsByTagName("os:tax");
foreach (XmlNode node in tax)
{
    XmlElement cat = (XmlElement)node;
    // than get string values here?
}

Is this correct? Can anyone show me efficient way to do this? Or right way to do this easily?

9
  • 10
    Can you use .NET 3.5 or higher? LINQ to XML makes this simpler... Commented Nov 18, 2011 at 18:54
  • @Jon i am using .NET 3.5 but i have never used LINQ. Can you explain me how to do it? Commented Nov 18, 2011 at 18:59
  • @Henk - structure is correct for xml file. As per the result i want id of each cat and there name, then get id of subcat its name, then get cut name, id and url, so probablly a loop to get all that. Commented Nov 18, 2011 at 19:00
  • 1
    @Gurnor, google for some LINQ to XML samples. Commented Nov 18, 2011 at 19:00
  • possible duplicate of Saving xml data in Oracle in C#. Asked 32 minutes before this one was. Commented Nov 18, 2011 at 19:02

3 Answers 3

5

Here's a sample for LINQ to XML - but I strongly suggest you look for full LINQ to XML tutorials. (And get to grips with the rest of LINQ...)

(EDIT: I hadn't spotted the t part before.)

XDocument doc = XDocument.Load("tax.xml");
XNamespace os = "http://something"; // You haven't included the declaration...

foreach (XElement cat in doc.Descendants(os + "cat"))
{
    int catId = (int) cat.Attribute("id");
    string catName = (string) cat.Attribute("name");

    foreach (XElement subcat in cat.Elements(os + "subcat"))
    {
        int subId = (int) subcat.Attribute("id");
        string subName = (string) subcat.Attribute("name");

        foreach (XElement t in subcat.Elements(os + "t"))
        {
            int tId = (int) t.Attribute("id");
            string tName = (string) t.Attribute("name");
            foreach (XElement cut in t.Elements(os + "cut"))
            {
                string cutId = (int) cut.Attribute("id");
                string cutName = (string) cut.Attribute("name");
                string cutUrl = (string) cut.Attribute("cutURL");
                // Use the variables here
            }
        }
    }
}

This assumes there's only one subcat for each cat - I don't know if that's correct.

You may want to express this as a LINQ query instead... it depends on what you need to do.

Here's a LINQ query version - having looked at everything you're using, I think this makes more sense:

XDocument doc = XDocument.Load("tax.xml");
XNamespace os = "http://something"; // You haven't included the declaration...

var query = from cat in doc.Descendants(os + "cat")
            from subcat in cat.Elements(os + "subcat")
            from t in subcat.Elements(os + "t")
            from cut in t.Elements(os + "cut")
            select new
            {
                CatId = (int) cat.Attribute("id"),
                CatName = (string) cat.Attribute("name"),
                SubCatId = (int) subcat.Attribute("id"),
                SubCatName = (string) subcat.Attribute("name"),
                TId = (int) t.Attribute("id"),
                TName = (string) t.Attribute("name"),
                CutId = (int) cut.Attribute("id")
                CutName = (string) cut.Attribute("name")
                CutUrl = (string) cut.Attribute("cutURL")
            };

Note that I've converted all the ID values to int rather than string. You could convert them to strings instead, of course, but if they are all integers, it makes sense to parse them as such.

Sign up to request clarification or add additional context in comments.

14 Comments

sorry forgot to mention it could have more than one subcat
@Gurnor: Will edit, but without knowing much more about what you need to do with them, it's somewhat hard to really give much concrete help. You should really find a LINQ to XML tutorial.
I'm not the downvoter, but it seems like there should be an easier way. Can't LINQ to XML traverse the document? Couldn't you just do: doc.Descendants(os + "cut")?
@JamesJohnson: You could indeed - but then you'd still need to get the parent elements for their attributes. It's easy enough to do, certainly. Does the second part of the answer look more friendly to you?
@JonSkeet: Second part definitely looks friendlier. I think it just looks more complicated than I'm used to because you're grabbing the attribute values at each level. LINQ query definitely looks a lot cleaner, though :)
|
2

Jon's suggestion to use LINQ to XML is the way to go, but I've included the old way below. My XPath is a little (very) rusty, so forgive me if there are any mistakes:

var doc = new XmlDocument(); //your document

var xmlnsManager = new System.Xml.XmlNamespaceManager(doc.NameTable);
xmlnsManager.AddNamespace("os", "http://bla");

foreach (XmlNode node in doc.SelectNodes("//os:subcat/os:t/os:cut", xmlnsManager))
{
    string value = node.Attributes.GetNamedItem("name").Value;
}   

See this article if you need more help: http://support.microsoft.com/kb/318545

Comments

0

Consider using XElement along with Lambda expression.

XNamespace osNs = "http://xml.com"; // Like Jon said, you haven't included the namespace url

XElement taxElement = XElement.Load("path/to/your/xml/file");


foreach(var cat in taxElement.Decendents(osNs + "cat"))
{
    Console.WriteLine(cat.Attribute("id").Value);

    foreach(var subcat in cat.Decendents(osNs + "subcat"))
    {
        Console.WriteLine(subcat.Attribute("id").Value);

        foreach(var t in subcat.Decendents(osNs + "t"))
        {
            Console.WriteLine(t.Attribute("id").Value);

            foreach(var cut in t.Decendents(osNs + "cut"))
            {
                Console.WriteLine(cut.Attribute("id").Value);
                Console.WriteLine(cut.Attribute("name").Value);
                Console.WriteLine(cut.Attribute("cutURL").Value);
            }
        }
    }
}

It's just capturing one node at by another. If you want to get all the curURL then you can just write something like this:

foreach(var cut in taxElement.Decendents(osNs + "cut")) { Console.WriteLine(cut.Attribute("cutURL")); }

Even you can use Lambda like if you want something like all os:cut where os:subcat id = 22

taxElement.Decendents("osNs + "subcat").Where(p => p.Attribute("id").Value == "22").Decendents(osNs + "cut");

Please go through some tutorial on LINQ to XML or something on XElement.

Hope this helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.