从父节点获取XML标记属性值到最后一个子节点

时间:2016-12-06 10:02:56

标签: c# xml linq

这是我的输入XML

nav.pushPage(['angular', 'route'])
nav.popPage(['goes','here'])

我想提取<?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> 并形成如下字符串:

TextField

我想在字符串中打印TextField的第一个标记值,直到TextField的最后一个标记值。下面是我尝试的代码,但是打印的所有TextField值都不是我需要的结构格式。

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

2 个答案:

答案 0 :(得分:1)

试试这个linq xml查询。确保您更换&#39;&amp;&#39;与&#39;&amp; amp;&#39;

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

}

答案 1 :(得分:1)

如果你想要与菜单的深度无关,你可以去递归:

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

你可以这样调用你的递归方法:

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

如果您不想打印根菜单,则必须从根目录下的元素开始:

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