【问题标题】:Save TreeView as xml with attributes and elements将 TreeView 保存为带有属性和元素的 xml
【发布时间】:2013-05-15 12:41:18
【问题描述】:

我有一个需要保存为 xml 文件的 Windows 窗体 TreeView。

TreeView的结构是这样的:

 - Parent
  - Child 1 (Any value)
  - Child 2
    - Child 1 (Any value for a child)

每个有子节点的 TreeNode 都需要保存为一个元素,每个没有子节点的 TreeNode 都需要保存为其父 TreeNode 的属性

这意味着上面会产生以下xml:

<?xml version="1.0" encoding="utf-8"?>
<Parent Child1="Any value">
  <Child2 Child1="Any value for a child" />
</Parent>

我尝试使用以下代码,但是当没有子节点的 TreeNodes 低于有子节点的 TreeNodes 时它不起作用,我真的想不出一个好的方法。

    public void SerializeTreeView(TreeView treeView, string fileName)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;

        XmlWriter textWriter = XmlWriter.Create(fileName, settings);

        // Writing the xml declaration tag
        textWriter.WriteStartDocument();

        // Save the nodes, recursive method
        SaveNodes(treeView.Nodes, textWriter);

        // End the xml document
        textWriter.WriteEndDocument();
        textWriter.Close();
    }

    private void SaveNodes(TreeNodeCollection nodesCollection, XmlWriter textWriter)
    {
        for (int i = 0; i < nodesCollection.Count; i++)
        {
            TreeNode node = nodesCollection[i];

            if (node.Nodes.Count > 0)
            {
                textWriter.WriteStartElement(node.Name);
            }
            else
            {
                textWriter.WriteAttributeString(node.Name, "Attribute value");
            }

            if (node.Nodes.Count > 0)
                SaveNodes(node.Nodes, textWriter);

            if (node.Nodes.Count > 0)
                textWriter.WriteEndElement();
        }
    }

编辑:

当前代码的问题是,如果我添加一个具有任何子节点且高于没有子节点的 TreeNode 的 TreeNode,则会出现以下错误:

Token StartAttribute in state Element Content would result in an invalid XML document.

这发生在:

textWriter.WriteAttributeString(node.Name, "Attribute value");

我通过按子节点计数对 TreeView 进行排序来解决它(这意味着没有子节点的 TreeNode 将始终低于没有子节点的 TreeNode)

解决方案有效,但我想弄清楚错误发生的原因以及如何修复它。

【问题讨论】:

  • 任何不考虑linq2xml的理由!
  • 发生错误是因为 XmlWriter 很烂。它写入文本流并且不会返回,因此您只能在“WriteStartElement”之后添加属性。
  • 谢谢,完成了这项工作。顺便说一句,非常漂亮的代码:)

标签: c# xml winforms recursion treenode


【解决方案1】:

你是如何填充 TreeView 的?你实际上是给对象键还是只是标题?尝试用“node.Text”替换两次出现的“node.Name”(并且,出于代码完整性的原因,重构 Count > 0 的多重检查):

编辑:好的,试试这个:

    private void SaveNodes(TreeNodeCollection nodesCollection, XmlWriter textWriter)
    {
        foreach (var node in nodesCollection.OfType<TreeNode>().Where(x => x.Nodes.Count == 0))
            textWriter.WriteAttributeString(node.Name, "Attribute value");

        foreach (var node in nodesCollection.OfType<TreeNode>().Where(x => x.Nodes.Count > 0))
        {
            textWriter.WriteStartElement(node.Name);
            SaveNodes(node.Nodes, textWriter);
            textWriter.WriteEndElement();
        }
    }

【讨论】:

  • TreeView 是通过读取 xml 文件并在该 xml 文件中查找子节点来填充的。这意味着每个 TreeNode 都有我使用的两个属性,名称和文本。名称设置为元素名称,文本设置为元素名称但已格式化(意思是“this-is-my-element”将显示为“This Is My Element”。当我保存 xml 文档时,TreeNode然后将 name 用作元素名称。
  • 那有什么问题吗? “但是当没有孩子的TreeNodes在有孩子的TreeNodes下面时它不起作用”它怎么不起作用?发生了什么?该代码适用于您在问题中给出的示例...
  • 啊,我明白了 - 未来的提示 - 发布一个导致问题的示例,而不是一个可以正常工作的示例。我更新了我的答案。
  • 谢谢您,对于不可靠的解释感到抱歉。我在我的帖子中添加了一个编辑,应该解释发生了什么。
猜你喜欢
  • 2020-04-08
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
相关资源
最近更新 更多