1

我有以下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 和 Groups,它们都具有“父”属性。

目前我这样迭代:

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)

谢谢

4

5 回答 5

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
}
于 2013-02-19T17:12:15.067 回答
1

由于您使用的是 Linq to XML,因此您可以使用Descendants方法 - 它返回所有子元素,而不仅仅是直接子元素。之后,您可以使用 LINQ 过滤结果。

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

如果您不能保证源 XML 不具有所有菜单元素的此类属性,您可能需要检查是否o.Attribute("url")不返回null(当属性不存在时会返回)。

您还可以跳过参数 toDescendants()检查所有元素 - 在您的示例数据中,这将允许您检查菜单和项目元素。例如:

var activeMenu = doc.Descendants()
     .Where(o => o.Name == "menu" || o.Name == "item")
     .FirstOrDefault(o => o.Attribute("url").Value == activePage);
于 2013-02-19T17:20:36.957 回答
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.XPath和选择节点。XPathSelectElementXPathSelectElements

于 2013-02-19T17:07:10.537 回答
0

您可以使用 XPath 做到这一点:

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

它将返回所有具有activePageasurl属性的文档项。

于 2013-02-19T17:15:56.657 回答
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)
于 2015-04-24T13:25:55.503 回答