将笨拙的 xml 文档结构转换为友好的结构

本文关键字:结构 转换 文档 xml | 更新日期: 2023-09-27 17:55:44

好的,所以我有一个自动生成的xml文件,它代表库中的某个文件夹结构:

<Folder>
    <Name>One</Name>
    <OutlineLevel>0</OutlineLevel>
</Folder>
<Folder>
    <Name>Two</Name>
    <OutlineLevel>1</OutlineLevel>
</Folder>
<Folder>
    <Name>Three</Name>
    <OutlineLevel>2</OutlineLevel>
</Folder>
<Folder>
    <Name>Four</Name>
    <OutlineLevel>3</OutlineLevel>
</Folder>
<Folder>
    <Name>Five</Name>
    <OutlineLevel>2</OutlineLevel>
</Folder>
<Folder>
    <Name>Six</Name>
    <OutlineLevel>3</OutlineLevel>
</Folder>
<Folder>
    <Name>Seven</Name>
    <OutlineLevel>3</OutlineLevel>
</Folder>
<Folder>
    <Name>Eight</Name>
    <OutlineLevel>1</OutlineLevel>
</Folder>

但是,我需要它在以下结构中看起来更人性化且不那么尴尬:

<Folder Name="One">
    <Folder Name="Two">
        <Folder Name="Three">
            <Folder Name="Four"></Folder>
        </Folder>
        <Folder Name="Five">
            <Folder Name="Six"></Folder>
            <Folder Name="Seven"></Folder>
        </Folder>
    </Folder>
    <Folder Name="Eight"></Folder>
</Folder>

我已经研究了一段时间,对于如何将其包装成一种方法,我没有任何想法。任何建议将不胜感激。

到目前为止,我已经成功地将其放入我类的对象中,如下所示:

class MyFolder
{
    private List<MyFolder> _folders;
    public List<MyFolder> Folders
    {
        get
        {   if (_folders == null)
            { _folders = new List<MyFolder>(); }
            return _folders;  }
        set { _folders = value; }
    }
    public string Name { get; set; }
}

老实说,不知道这是否会导致我去任何地方,我现在有一个MyFolder,其中包含MyFolder,其中包含其他MyFolder等,希望这是有意义的。

将笨拙的 xml 文档结构转换为友好的结构

我做了一个控制台应用程序。它产生您需要的东西。我已将您的XML包装到文件夹树元素中,只是为了使解析变得容易。

static void Main(string[] args)
{
    var xml = @"<FolderTree>
        <Folder>
            <Name>One</Name>
            <OutlineLevel>0</OutlineLevel>
        </Folder>
        <Folder>
            <Name>Two</Name>
            <OutlineLevel>1</OutlineLevel>
        </Folder>
        <Folder>
            <Name>Three</Name>
            <OutlineLevel>2</OutlineLevel>
        </Folder>
        <Folder>
            <Name>Four</Name>
            <OutlineLevel>3</OutlineLevel>
        </Folder>
        <Folder>
            <Name>Five</Name>
            <OutlineLevel>2</OutlineLevel>
        </Folder>
        <Folder>
            <Name>Six</Name>
            <OutlineLevel>3</OutlineLevel>
        </Folder>
        <Folder>
            <Name>Seven</Name>
            <OutlineLevel>3</OutlineLevel>
        </Folder>
        <Folder>
            <Name>Eight</Name>
            <OutlineLevel>1</OutlineLevel>
        </Folder>
        </FolderTree>
    ";
    var root = XElement.Parse(xml);
    var elements = root.Elements().ToList();
    var rootFolderString = GetItemsAtLevel(new Queue<XElement>(elements), 0).First().ToString();
}
private static void TransformElement(XElement folder)
{
    folder.Element("OutlineLevel").Remove();
    var nameElement = folder.Element("Name");
    nameElement.Remove();
    folder.Add(new XAttribute(nameElement.Name, nameElement.Value));
}
private static IEnumerable<XElement> GetItemsAtLevel(Queue<XElement> elements, int level)
{
    while (elements.Any())
    {
        var parent = elements.Dequeue();
        var children = new Queue<XElement>();
        while (elements.Any() && (int)elements.Peek().Element("OutlineLevel") > level)
        {
            children.Enqueue(elements.Dequeue());
        }
        if (children.Any())
        {
            var subtree = GetItemsAtLevel(children, level + 1);
            parent.Add(subtree);
        }
        TransformElement(parent);
        yield return parent;
    }
}