简体   繁体   中英

Iterate through XML and change parent properties

I'm currently generating XML for a SharePoint site structure recursively (the SharePoint is just background, the issue is the XML). This gets a list of all sites and subsites. I then get all lists a user has access to, the structure looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<sites>
    <site title="Home" url="/">
        <site title="RestApp" url="/RestApp" />
        <site title="SiteMap" url="/SiteMap" />
        <site title="subsite" url="/subsite">
            <list title="Documents" url="/subsite" />
            <site title="anothersite" url="/subsite/another" />
        </site>
        <site title="Template" url="/TemplatePicker" />
        <site title="test" url="/test">
            <site title="testing" url="/test/testing">
                <site title="blah" url="/test/testing/blah">
                    <list title="Documents" url="/test/testing/blah" />
                </site>
            </site>
        </site>
        <site title="TestApp" url="/TestApp" />
    </site>
</sites>

I now need to iterate back through the xml and remove any sites that don't have a list element as a child (or don't have an element with a list as a child). However, I am having trouble propagating this back to the parent nodes. So the above xml would become:

<?xml version="1.0" encoding="UTF-8"?>
<sites>
    <site title="Home" url="/">
        <site title="subsite" url="/subsite">
            <list title="Documents" url="/subsite" />
        </site>
        <site title="test" url="/test">
            <site title="testing" url="/test/testing">
                <site title="blah" url="/test/testing/blah">
                    <list title="Documents" url="/test/testing/blah" />
                </site>
            </site>
        </site>
    </site>
</sites>

I did write a post-order traversel that adds a new attribute to the leaf elements that says if it's visible. However, I am unable to propogate this backup more than one element so it isn't a viable solution.

The other option I have looked at is going through each node and checking if any of the children have 'list' as a name. But I'm not sure if this is viable given the size of the site.

The best way to iterate through a hierarchical structure is a recursion.

I would do this this using head recursion :

public static void RemoveEmpty(XmlNode node)
{
    foreach (XmlNode child in node.SelectNodes("site"))
        RemoveEmpty(child);

    if (!node.HasChildNodes) node.ParentNode.RemoveChild(node);
}

That's how it works:

  1. Recursively go through the tree down to the leafs
  2. Recursively return back to the root through the hierarchy doing the following at every node:
    • If this node doesn't have child nodes - remove it

According to this algorithm, at every iteration all of current node's child nodes are already processed and don't have empty child notes .
Non- <site> tags are ignored and not being checked and removed but they are counted during check for having child nodes.

Now you only need to run this function from your root node.

XmlDocument document = new XmlDocument();

document.LoadXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?><sites> <site title=\"Home\" url=\"/\"> <site title=\"RestApp\" url=\"/RestApp\" /> <site title=\"SiteMap\" url=\"/SiteMap\" /> <site title=\"subsite\" url=\"/subsite\"> <list title=\"Documents\" url=\"/subsite\" /> <site title=\"anothersite\" url=\"/subsite/another\" /> </site> <site title=\"Template\" url=\"/TemplatePicker\" /> <site title=\"test\" url=\"/test\"> <site title=\"testing\" url=\"/test/testing\"> <site title=\"blah\" url=\"/test/testing/blah\"> <list title=\"Documents\" url=\"/test/testing/blah\" /> </site> </site> </site> <site title=\"TestApp\" url=\"/TestApp\" /> </site></sites>");

RemoveEmpty(document.SelectSingleNode("sites"));

Console.WriteLine(document.OuterXml);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM