Using LINQ to filter XML file

Go To StackoverFlow.com

0

I have an XML file that looks like this:

<SiteMenuItems>
    <SiteMenuItem text="Home" navigateurl="/Default.aspx" tooltip="Return Home" />
    <SiteMenuItem text="Admin" roles="Admin">    
        <SiteMenuItem text="User Admin" navigateurl="/Authorized/UserAdmin/Default.aspx" roles="SuperAdmin" />
    </SiteMenuItem>
</SiteMenuItems>

Using the example I found at at this StackOverflow question, I was able to come up with the following code:

    public string GetMenu()
    {

        XDocument xmlDoc = XDocument.Load(HttpContext.Current.Server.MapPath(@"~/App_Data/SiteMenu.xml"));
        xmlDoc = FilterRoles(xmlDoc); //Working on role problem
        return ExecuteXSLTransformation(xmlDoc.ToString());
    }

    private XDocument FilterRoles(XDocument xmlDoc)
    {
        XElement element = xmlDoc.Element("SiteMenuItems");
        XElement root = new XElement("SiteMenuItems",
                        (
                            from sm
                            in element.Elements("SiteMenuItem")
                            where UserHelper.IsUserAuthorized(sm.Attribute("roles"))
                            select new XElement(sm))
                        );

        XDocument menuXml = new XDocument();
        menuXml.Add(root);
        return menuXml;
    }

The problem I have is that the code is only filtering the first level:

<SiteMenuItem text="Admin" roles="Admin">

But I can't figure out how to filter the internal SiteMenuItem as well:

<SiteMenuItem text="User Admin" navigateurl="/Authorized/UserAdmin/Default.aspx" roles="SuperAdmin" />

As it is now, if you have the Admin role, it also returns the "User Admin" item.

[UPDATE] Thanks to woodings, my child nodes are now going through the "IsUserAuthorized" test.

Unfortunately, even though the test is returning "false" for the "User Admin" node, that node is still getting returned as part of the overall XML document.

I was hoping it would return something like this:

<SiteMenuItems>
    <SiteMenuItem text="Home" navigateurl="/Default.aspx" tooltip="Return Home" />
    <SiteMenuItem text="Admin" roles="Admin">    
    </SiteMenuItem>
</SiteMenuItems>

Any ideas?

Thanks again!!

2012-04-05 00:29
by Duane Haworth


0

I solved my problem and even eliminated the FilterRoles() method:

public string GetMenu() 
{
    XDocument xmlDoc = XDocument.Load(HttpContext.Current.Server.MapPath(WebConfigHelper.GetSiteMenu));

    xmlDoc.Descendants().Where(element => !UserHelper.IsUserAuthorized(element.Attribute("roles"))).Remove();

    return XsltTransformHelper.ExecuteXslTransformation(xmlDoc.ToString(), HttpContext.Current.Server.MapPath(WebConfigHelper.GetSiteMenuTransform));
}

Thanks for everyone's help!!!

2012-04-06 01:47
by Duane Haworth


4

XElement.Elements() returns only immediate children of that particular element. Use XElement.Descendants() instead.

private XDocument FilterRoles(XDocument xmlDoc)
{
    XElement element = xmlDoc.Element("SiteMenuItems");
    XElement root = new XElement("SiteMenuItems",
                    (
                        from sm
                        in element.Descendants("SiteMenuItem")
                        where UserHelper.IsUserAuthorized(sm.Attribute("roles"))
                        select new XElement(sm))
                    );

    XDocument menuXml = new XDocument();
    menuXml.Add(root);
    return menuXml;
}
2012-04-05 00:35
by woodings
THANK YOU, THANK YOU, THANK YOU!!! It is now testing child items!! However, the child item 'User Admin' is still getting displayed, even though it's set to false from the 'IsUserAuthorized' method - Duane Haworth 2012-04-05 00:44
Ads