简体   繁体   中英

Get XML tag attribute value from parent node to last child node

This is my input XML

<?xml version="1.0" encoding="UTF-8"?>
<Menu TextField="Menu">
   <Menu TextField="Approvals">
      <Menu TextField="Vacation/Leave">
         <Menu TextField="Vacation Pre-Request Approval" />
         <Menu TextField="Vacation Approval" />
      </Menu>
      <Menu TextField="Late Come Approval" />
      <Menu TextField="Loan Approval" />
      <Menu TextField="Department Change Approval" />
      <Menu TextField="Resignation/Termination">
         <Menu TextField="Resignation Approval" />
         <Menu TextField="Resignation Clearance" />
      </Menu>
   </Menu>
   <Menu TextField="Employee Transactions">
      <Menu TextField="Change Designation" />
      <Menu TextField="Organization">
         <Menu TextField="Organization Designation & Grade" />
      </Menu>
      <Menu TextField="Change Grade" />
   </Menu>
</Menu>

I would to extract the TextField and form a string like below:

Approvals > Vacation/Leave > Vacation Pre-Request Approval
Approvals > Vacation/Leave > Vacation Approval
Approvals > Late Come Approval
Approvals > Loan Approval
Approvals > Department Change Approval
Approvals > Resignation/Termination > Resignation Approval
Approvals > Resignation/Termination > Resignation Clearance
Employee Transactions > Change Designation
Employee Transactions > Organization > Organization Designation & Grade
Employee Transactions > Change Grade

I would to print first tag value of TextField till last tag value of TextField in a string. Below is the code I tried but that print all TextField values not in structure format I require.

var menus = (from menu in XDocument.Parse(xml).Descendants("Menu")
            select new
                {
                    TextField = (string)menu.Attribute("TextField")
                }).ToList();

Try this linq xml query. Make sure you replace '&' with '&amp;'

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;



namespace ConsoleApplication29
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            XElement menu = doc.Descendants().Where(x => (string)x.Attribute("TextField") == "Menu").FirstOrDefault();
            foreach (XElement element in menu.Elements())
            {
                string textField = (string)element.Attribute("TextField");
                foreach (XElement subElement in element.Elements())
                {
                    List<string> textStrings = subElement.DescendantNodesAndSelf().Select(x => (string)((XElement)x).Attribute("TextField")).ToList();
                    textStrings.Insert(0, textField);
                    Console.WriteLine(string.Join(" > ", textStrings));
                }
            }
            Console.ReadLine();
        }
    }

}

In case you want to be indipendent from the depth of your menu, you can go for recursion:

IEnumerable<string> GetMenuTexts(XElement menuElement) {
    string ownText = menuElement.Attribute("TextField").Value;
    if (!menuElement.Elements("Menu").Any()) {
        return new string[] { ownText };
    }
    else {
        var menus =
            from subMenuElement in menuElement.Elements("Menu")
            from menuText in GetMenuTexts(subMenuElement)
            select ownText + " > " + menuText;
        return menus;
    }
}

You call your recursive method like this:

var menus = (from menuText in GetMenuTexts(XDocument.Parse(xml).Root)
            select new
                {
                    TextField = menuText
                }).ToList();

If you don't want to print the root menu, you have to start from the elements under the root:

var menus = (from menuElement in XDocument.Parse(xml).Root.Elements("Menu")
            from menuText in GetMenuTexts(menuElement)
            select new
                {
                    TextField = menuText
                }).ToList();

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