2016-12-06 115 views
0

從父節點XML標記屬性值。這是我的輸入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> 

我想提取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 

我向將TextField的第一個標記值打印到字符串中TextField的最後一個標記值。以下是我嘗試過的代碼,但是打印的所有TextField值不是我需要的結構格式。

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

回答

1

如果你想從你的菜單深度indipendent,你可以去遞歸:

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(); 
+0

無法從'System.Collections.Generic.IEnumerable '轉換爲'System.Xml.Linq.XElement' –

+0

您是對的。我編輯了我的答案。 – Sefe

+0

太棒了!它也打印菜單。我不想在列表中打印。任何想法? –

1

試試這個linq xml查詢。確保你將'&'替換爲'& 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(); 
     } 
    } 

} 
+0

這是我見過的最美麗的答案之一。但是這樣的打印答案是:Approvals> Vacation/Leave> Vacation Pre-Request Approval> Vacation Approval –

+0

但我希望像Approvals> Vacation/Leave> Vacation Pre-Request Approval Approvals> Vacation/Leave> Vacation Approval –

+0

If Sefe hasn給你的代碼。我可以修改。爲了獲得預期的結果,我需要修改代碼以使用遞歸方法()。 – jdweng