2012-02-19 47 views
3

我想在下面的示例中獲取所有的子頁面。 XML看起來像這樣(簡單的佈局)我如何找到我的XML中的所有子節點

<?xml version="1.0"?> 

<main> 
    <group title="Server Tools" enabled="True"> 
    <page title="Server Tools" pageId="1" subtitle="Tools for servers" enabled="True"> 
     <subpage title="Name-1" pageId="2" subtitle="" enabled="True">   
     <subpage title="Name-2" pageId="3" subtitle="" enabled="True"> 
      <subpage title="Name-3" pageId="4" subtitle="" enabled="True"> 
       <subpage title="Name-4" pageId="5" subtitle="" enabled="True">     
       </subpage> 
      </subpage> 
     </subpage> 
     </subpage> 
    </page> 
    </group> 
</main> 

我試圖創建以下,但它只發現第一個「子頁面」。

XmlDocument doc = new XmlDocument(); 
doc.Load(path + @"\config.xml"); 

XmlNodeList groups = doc.SelectNodes("main/group"); 
foreach (XmlNode group in groups) 
{ 
    String groupTitle = group.Attributes["title"].InnerText; 
    String groupEnabled = group.Attributes["enabled"].InnerText; 
    maxResults = Convert.ToInt32(group.Attributes["maxResults"].InnerText); 

    if (groupEnabled == "True") 
    { 
     firstGroup.Title = groupTitle; 
     XmlNodeList pages = group.SelectNodes("page"); 

     foreach (XmlNode page in pages) 
     { 
      String pageTitle = page.Attributes["title"].InnerText; 
      int pageId = Convert.ToInt32(page.Attributes["pageId"].InnerText); 
      String subtitle = page.Attributes["subtitle"].InnerText; 
      String pageEnabled = page.Attributes["enabled"].InnerText; 

      if(pageEnabled == "True") 
      { 
      firstGroup.Items.Add(new PageItem(pageId, pageTitle, subtitle)); 
      pageList.Add(pageId); 
      XmlNodeList subpages = page.SelectNodes("subpage"); 

      foreach (XmlNode subpage in subpages) 
      { 
       string subpageTitle = subpage.Attributes["title"].InnerText; 
       int subpageId = Convert.ToInt32(subpage.Attributes["pageId"].InnerText); 
       String subpageSubtitle = subpage.Attributes["subtitle"].InnerText; 
       String subpageEnabled = subpage.Attributes["enabled"].InnerText; 

       if (subpageEnabled == "True") 
       { 
        subpageDic.Add(subpageId, new Tuple<int, string, string>(pageId, subpageTitle, subpageSubtitle)); 
       } 
      } 
      } 
     } 
    } 
} 

我在做什麼錯?我只想瀏覽子頁面下的所有子頁面並獲取可用的屬性。

在此先感謝。

+2

問題可能是子頁面嵌套。 – Krizz 2012-02-19 21:11:56

+0

嘗試使用遞歸來遍歷嵌套的子頁面。 – pistipanko 2012-02-19 21:18:07

+0

嗨Krizz,嗯沒關係,有沒有更簡單的方法來做這個佈局呢。我希望能夠擁有多個頁面節點和子頁面,但是如果需要的話,一個子頁面也應該有sub,sub,sub頁面。任何想法;) – cptrico 2012-02-19 21:18:55

回答

1

你的問題是在這裏

XmlNodeList subpages = page.SelectNodes("subpage"); 

subpages只包含兒童包含在page元素的subpage元素。

但是,您希望所有後代page

與此替換上面的行:

XmlNodeList subpages = page.SelectNodes(".//subpage"); 

可變subpages現在包含當前節點page的所有subpage後代。

+0

非常乾淨的答案感謝,這是你的問題,這是你如何解決它,我喜歡這個。謝謝。它現在正在按我希望的方式工作。 – cptrico 2012-02-20 12:36:15

+0

@cptrico:不客氣。 – 2012-02-20 15:29:22

0

忘記XMLDocument並改用LINQ to XML。一旦你使用XDocument.Load()加載文件,你可以使用代碼,如

IEnumerable<XElement> de= 
    from el in xmlTree.Descendants("subpage") 
    select el; 
    foreach (XElement el in de) 
Console.WriteLine(el.Attributes("title"), el.Attributes("pageID"));//etc 
+0

這將只會得到頂級'subpage'元素(4 ,使用示例),而不是**全部**(10,再次來自示例)。 – Yuck 2012-02-19 21:18:44

+1

不,我想它會返回所有的子頁面元素,包括頂層元素。它不會獲得有關關聯頁面元素的信息,但是當查看問題中的代碼段時,我不確定是否需要它。 – 2012-02-19 21:41:05

+0

不,它返回所有子頁面元素。請參閱http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.descendants.aspx。它比我見過的任何其他代碼都容易得多:-) – deadlyvices 2012-02-20 10:56:35

0

這個怎麼樣?

 string path = @"..\LinqToXml\LinqToXml\config.Xml"; 

     XElement doc2 = XElement.Load(path); 

     var element = from t in doc2.Elements("group").Elements("page").Descendants() select t; 

     foreach (var el in element) 
     { 
      if (el.HasAttributes) 
      { 
       foreach (var att in el.Attributes()) 
       { 
        Debug.WriteLine(att.Value); 
       } 
      } 
     } 
+1

您正在選擇*全部*,而不僅僅是'subpage'元素。 – Yuck 2012-02-19 21:26:18

+0

感謝您的快速回復。如果難以嵌套,你認爲將我的xml更改爲其他東西會更好嗎?要麼 ?只需要能夠支持多個子平面。 (yuck)你知道我應該怎麼做才能解決這個問題。 :) – cptrico 2012-02-19 21:31:54

+0

堅持你的格式,看看我使用LINQ to XML的答案。它會工作,相信我。 – deadlyvices 2012-02-20 11:05:26

2

也許與XPATH嘗試:

XmlDocument document = ...; 
var nodes = document.SelectNodes("//subpage"); 

nodes將包含此集合:

<subpage title="Name-1" pageId="2" subtitle="" enabled="True">   
    <subpage title="Name-2" pageId="3" subtitle="" enabled="True"> 
     <subpage title="Name-3" pageId="4" subtitle="" enabled="True"> 
       <subpage title="Name-4" pageId="5" subtitle="" enabled="True">     
       </subpage> 
      </subpage> 
     </subpage> 
    </subpage> 
<subpage title="Name-2" pageId="3" subtitle="" enabled="True"> 
    <subpage title="Name-3" pageId="4" subtitle="" enabled="True"> 
    <subpage title="Name-4" pageId="5" subtitle="" enabled="True">     
</subpage> 

現在,在節點每個節點選擇遞歸//subpage

編輯:

XPATH是一個強大的工具。試試這個xpath://../subpage。其結果是:

<subpage title="Name-1" pageId="2" subtitle="" enabled="True">   
     <subpage title="Name-2" pageId="3" subtitle="" enabled="True"> 
      <subpage title="Name-3" pageId="4" subtitle="" enabled="True"> 
       <subpage title="Name-4" pageId="5" subtitle="" enabled="True">     
       </subpage> 
      </subpage> 
     </subpage> 
    </subpage> 
----------------------- 
<subpage title="Name-2" pageId="3" subtitle="" enabled="True"> 
    <subpage title="Name-3" pageId="4" subtitle="" enabled="True"> 
     <subpage title="Name-4" pageId="5" subtitle="" enabled="True">     
     </subpage> 
    </subpage> 
</subpage> 
----------------------- 
<subpage title="Name-3" pageId="4" subtitle="" enabled="True"> 
    <subpage title="Name-4" pageId="5" subtitle="" enabled="True">     
    </subpage> 
</subpage> 
----------------------- 
<subpage title="Name-4" pageId="5" subtitle="" enabled="True"> 
</subpage> 
+0

謝謝你的例子:)非常有幫助完整。 – cptrico 2012-02-20 12:35:33

0

一旦轉換成的XElement,你可以使用XPathSelectElements extension方法以「//」以及選擇具有特定名稱的所有元素。

using System.Xml.XPath; 

... 

var path = "<Your path>"; 
var doc = XElement.Load(path); 

var subPages = doc.XPathSelectElements("//subpage[@pageId != '']") 
        .Select(x => new 
           { 
            Id = Convert.ToInt32(x.Attribute("pageId").Value, 
            SubTitle = x.Attribute("subtitle").Value, 
            Enabled = Convert.ToBoolean(x.Attribute("enabled").Value) 
           } 
       ) 
        .ToDictionary(u => u.Id, u => new Tuple<int, string, string>(u.Id, u.SubTitle, u.Enabled) 
+0

注:在XML中存在「字幕」和「啓用」屬性的假設有點不安全,並且沒有安全地確認「pageId」和「啓用」屬性值解析爲預期類型。將這部分留給你... – Reddog 2012-02-19 21:50:24

相關問題