0

我有一个来自用户的 LDAP(活动目录)及其经理的输出 xml,如下所示。我需要重新排序用户,以便在创建用户时按照管理层次结构的顺序创建它们。user 和 manager 子节点中的 dn 字段是链接值。这样当我们的用户导入例程处理它们时,我们就不必在尚未创建经理时为用户分配经理。Linqtoxml 可以做到这一点吗?

 <?xml version="1.0" encoding="utf-8"?>
<syncdata>
    <users> 
        <user>
            <dn>User2</dn>   
            <manager><dn>User1</dn></manager>
        </user>
        <user>
            <dn>User1</dn>   
            <manager><dn>User5</dn></manager>
        </user>  
        <user>
            <dn>User4</dn>   
            <manager><dn>User1</dn></manager>
        </user>
        <user>
            <dn>User5</dn>   
            <manager><dn>User3</dn></manager>
        </user>
        <user>
            <dn>User3</dn>   
            <manager><dn></dn></manager>
        </user>
    </users>
</syncdata>  

更新:重新格式化 xml,因为建议部分有效。它以前是无效的,因为有一个循环引用。

4

2 回答 2

1
    var element = XElement.Load(yourXmlPath);

    var ordered=element.Element("users").Elements().OrderBy(u => u.Element("manager").Element("dn").Value);

    element.Element("users").ReplaceAll(ordered);
于 2013-10-18T09:04:56.687 回答
1

这个选项会给你一个 sorted IOrderedEnumerable,每个用户的 xml 和 managerId 分开。这种变化应该给你很大的灵活性:

var sortedUsers =
     yourRootXElement.Element("users")
                     .Elements()
                     .Select(usr => 
                               new {
                                     managerId = usr.Element("manager")
                                                    .Element("dn")
                                                    .Value, 
                                     user = usr
                                    }) 
                     .OrderBy(user => user.managerId);

更新:

根据其他答案之一下的评论,您似乎想“递归地”重新排序(有点)。

最初,我并不认为使用 Linq 很容易 - 除非您可以选择操作原始 XML,否则您最好为此编写递归算法。

但是,如果您可以在 XML 中为每个用户添加一个字段depth,则它看起来像这样..:

<syncdata>
    <users> 
        <user>
            <dn>User2</dn>   
            <manager><dn>User1</dn></manager>
            <depth>2</depth>

        </user>
        <user>
            <dn>User1</dn>   
            <manager><dn>User5</dn></manager>
            <depth>1</depth>
        </user>  
        <user>
            <dn>User4</dn>   
            <manager><dn>User1</dn></manager>
            <depth>2</depth>
        </user>
        <user>
            <dn>User5</dn>   
            <manager><dn>User3</dn></manager>
            <depth>1</depth>
        </user>
        <user>
            <dn>User3</dn>   
            <manager><dn></dn></manager>
            <depth>0</depth> <!-- Note: Root element in hierarchy! -->
        </user>
    </users>
</syncdata>

...那么您也许可以按如下方式订购它?:

var sortedUsers =
    yourRootXElement.Element("users")
                    .Elements()
                    .Select(usr => 
                                new {
                                    userId =  usr.Element("dn").Value,
                                    managerId = usr.Element("manager")
                                                   .Element("dn")
                                                   .Value,
                                    depth = usr.Element("depth")
                                               .Value,
                                    userData = usr
                                })
                    .OrderBy(user => user.depth)
                    .ThenBy(user => user.managerId);

注意:这应该按照他们在层次结构中的“报告级别”对它们进行排序,但不会显示在他下面列出的经理下的那些 - 即:所有向顶级经理报告的人将首先显示,然后是所有那些向二级经理汇报,等等……

于 2013-10-18T09:15:42.987 回答