2013-02-19 147 views
1

我有以下XML:在xml中查找具有特定屬性的元素?

<?xml version="1.0" encoding="utf-8" ?> 
<layout> 
    <menu name="Employees" url="Employees.aspx" admin="0"> 
    </menu> 
    <menu name="Projects" url="Projects.aspx" admin="1"> 
    </menu> 
    <menu name="Cases" url="Cases.aspx" admin="1"> 
    </menu> 
    <menu name="CaseView" url="CaseView.aspx" admin="1" hidden="1" parent="Projects"> 
    </menu> 
    <menu name="Management" url="" admin="1"> 
    <item name="Groups" url="Groups.aspx" admin="1" parent="Management"/> 
    <item name="Statuses" url="Statuses.aspx" admin="1"/> 
    </menu> 
</layout> 

這裏我有CaseView和組都有一個「父」屬性。

目前我重複這樣的:

IEnumerable<XElement> menus = 
      doc.Element("layout").Elements(); 

      foreach (var menu in menus) 
      { 
        string name = menu.Attribute("name").Value; 
       string active = ""; 
       string url = menu.Attribute("url").Value; 
       if(activePage == url) 
       { 
        active = "class=\"active\""; 
       } 
       ... 

我要的是:

 if(activePage == url || ActiveIsChildOf(name, activePage)) 
     { 
      active = "class=\"active\""; 
     } 

本質上這種方法需要找到如果與activePage元素作爲其url屬性存在。如果有,請查看它是否具有父屬性;如果是這樣,請檢查父==的名稱。

有沒有某種方法來查找元素的屬性或東西? 例如:

XElement e = doc.GetByAttribute("url",activePage) 

感謝

回答

1

由於您使用Linq to XML,因此您可以使用Descendants方法 - 它將返回所有子元素,而不僅僅是直接子元素。之後,您可以使用LINQ來過濾結果。

XDocument doc; 
string activePage; 
var activeMenu = doc.Descendants("menu") 
    .FirstOrDefault(o => o.Attribute("url").Value == activePage); 

您可能需要檢查是否o.Attribute("url")沒有返回null(當屬性不存在它),如果你不能保證源XML沒有爲所有的菜單等元素屬性。

您也可以跳過參數到Descendants()來檢查所有元素 - 在您的示例數據中可以檢查菜單和項目元素。例如:

var activeMenu = doc.Descendants() 
    .Where(o => o.Name == "menu" || o.Name == "item") 
    .FirstOrDefault(o => o.Attribute("url").Value == activePage); 
0

您可以簡單地使用xPath。這是一個查詢語言XML

您可以制定這樣的事情:

var xDoc = new XmlDocument(); 
xDoc.Load("XmlFile.xml"); 

//Fetch your node here 
XmlNode = xDoc.SelectSingleNode(/layout/menu[@url='activepage'][1]); 

它返回一組節點和索引1是獲取給定的第一個節點。

如果您想要所有匹配的節點,則始終可以使用xDoc.SelectNodes


由於您使用LINQ你可以簡單地包括System.Xml.XPathXPathSelectElementXPathSelectElements選擇的節點。

1

如果XPath是太神祕,你可以使用LINQ:

IEnumerable<XElement> hits = 
     (from el in XMLDoc.root.Elements("item") 
     where (string)el.Attribute("url") == activePage 
     select el); 

或像這樣:

XElement xml = XElement.Load(file); 
XElement xele = xml.Elements("item").FirstOrDefault(e => ((string)e.Attribute("url")) == activePage); 
if(null != xele) 
{ 
    // do something with it 
} 

而且你可能希望它不區分大小寫:

XElement xml = XElement.Load(file); 
XElement xele = xml.Elements("item").FirstOrDefault(e => StringComparer.OrdinalIgnoreCase.Equals((string)e.Attribute("url") , activePage)); 
if(null != xele) 
{ 
    // do something with it 
} 

如果你想要菜單和項目,使用這個:

XElement xml = XElement.Load(file); 
XElement xele = xml.Elements().FirstOrDefault(e => StringComparer.OrdinalIgnoreCase.Equals((string)e.Attribute("url") , activePage)); 
if(null != xele) 
{ 
    // do something with it 
} 
+0

Niice不知道這一點。對我來說,LINQ和Lambdas的waaaaaay比XPath更神祕,但是因爲他在上面的例子中使用了它,所以我猜這對他來說可能是一個更簡單的解決方案。 – phadaphunk 2013-02-19 17:15:25

+0

這將返回所有或只'元素'元素我也有'菜單'的元素。 – jmasterx 2013-02-19 17:20:07

+0

第二個最後一個只找到屬性url =「activePage」類型的「item」類型的第一個元素,第一個元素的類型爲「item」,屬性url =「activePage」,最後一個是任何類型的第一個元素具有屬性activepage – 2013-02-19 17:38:25

0

你可以做到這一點的XPath:

doc.SelectNodes("//*[@url='" + activePage + "']") 

它會返回activePageurl屬性都文件的項目。

0

不區分大小寫的搜索示例,將XML轉換爲詞典:

Dim expandos = XDocument.Parse(Request("Xml")).Root.Elements.Select(
    Function(e) 
     Dim expando As Object = New ExpandoObject, 
      dic = e.Attributes.ToDictionary(Function(a) a.Name.LocalName, Function(a) a.Value, 
       StringComparer.InvariantCultureIgnoreCase) 
     expando.PedidoId = dic("PedidoId") 
     expando.FichaTecnicaModeloId = dic("FichaTecnicaModeloId") 
     expando.Comodo = dic("Comodo") 
     expando.Cliente = dic("Cliente") 
     Return expando 
    End Function) 
相關問題