2012-02-19 59 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

相关问题