【问题标题】:How to add new nodes to xml file如何将新节点添加到 xml 文件
【发布时间】:2017-01-23 02:06:19
【问题描述】:

我正在尝试将节点添加到 xml 文件中。

XML 文件:

<Students>
 <Student>
  <Address> ... </Address>
  <Grade> ... </Grade>
 </Student> 
  ...
</Students>

这是我所做的:

public XmlElement createNode(XmlDocument xmlDoc)
{
    XmlElement trElement = xmlDoc.CreateElement("Descriptions");
    XmlElement textElement = xmlDoc.CreateElement("Text");
    textElement.SetAttribute("String", "Abcdef");
    textElement.SetAttribute("Language", "ENG");
    trElement.AppendChild(textElement);
    return trElement;
}
public void doWork(string filePath)
{
    XmlDocument fromXML;
    fromXML = new XmlDocument();
    fromXML.Load(filePath);
    XmlNode fromRoot = fromXML.DocumentElement;
    foreach (XmlNode node in fromRoot.ChildNodes)
    {
        if (node.ChildNodes[0].Name != "Descriptions")
        {
            var trElement = createNode(fromXML);
            node.InsertBefore(trElement, node.ChildNodes[0]);
        }
    }
    fromXML.Save(Console.Out);
}

上面的代码会将节点Descriptions 添加到每个Student。如何将节点 Descriptions 添加到 xml 树中更深的其他节点?当前循环遍历学生但未遍历,例如:Grade

【问题讨论】:

  • 嵌套的 for 循环不能完成这个例子的任务吗?
  • 你能给我举个例子吗?
  • 我想你可能需要在这里递归。
  • @Neel 是的,这也是我之前的想法,但我现在不知道如何实现它。
  • @Sam 我已经用 xpath 和嵌套 for 循环更新了答案(您可以根据自己的情况选择)

标签: c# xml


【解决方案1】:

需要递归添加节点,详情查看代码中的cmets。

public static XmlNode CreateNode(XmlDocument document)
    {
        XmlElement trElement = document.CreateElement("Descriptions");
        XmlElement textElement = document.CreateElement("Text");
        textElement.SetAttribute("String", "Abcdef");
        textElement.SetAttribute("Language", "ENG");
        trElement.AppendChild(textElement);
        return trElement;
    }

    public static void doWork(string filePath)
    {
        XmlDocument fromXML;
        fromXML = new XmlDocument();
        fromXML.Load(filePath);
        XmlNode fromRoot = fromXML.DocumentElement;
        // Start from <Student></Student>
        foreach (XmlNode node in fromRoot.ChildNodes)
        {
            InsertNewNodes(node, fromXML);
        }
        fromXML.Save(Console.Out);
    }

    public static void InsertNewNodes(XmlNode root, XmlDocument document)
    {
        var hasDescription = false;

        // Iterate over every first level child looking for "Descriptions"
        foreach (XmlNode node in root.ChildNodes)
        {
            if (node.Name == "Descriptions")
            {
                hasDescription = true;
            }
            // recursively call InsertNewNodes
            if (node.ChildNodes.Count > 0)
            {
                InsertNewNodes(node, document);
            }
        }
        // Adjust the root.LastChild.NodeType criteria to only add the nodes when you want
        // In this case I only add the Description if the subnode has Elements
        if (!hasDescription && root.LastChild.NodeType == XmlNodeType.Element)
        {
            var newNode = CreateNode(document);
            root.PrependChild(newNode);
        }
    }

【讨论】:

    【解决方案2】:

    如果您只需要 1 级更新,则可以使用嵌套 for 循环,如下所示:

    public void doWork(string filePath)
    {
        XmlDocument fromXML;
        fromXML = new XmlDocument();
        fromXML.Load(filePath);
        XmlNode fromRoot = fromXML.DocumentElement;
        foreach (XmlNode node in fromRoot.ChildNodes)
        {
            foreach (XmlNode childNode in node) {
                if (childNode.Name == "Grade")
                {
                    if (childNode.ChildNodes[0].Name != "Descriptions")
                    {
                        var trElement = createNode(fromXML);
                         childNode.InsertBefore(trElement, childNode.ChildNodes[0]);
    
                    }
                }
            }
    
        }
        fromXML.Save(Console.Out);
    }
    

    但更好的方法是使用 Xpath,即使它不止一个级别,它也会让您无需递归即可获得节点

    public void doWork(string filePath)
            {
                XmlDocument fromXML;
                fromXML = new XmlDocument();
                fromXML.Load(filePath);
                XmlNode fromRoot = fromXML.DocumentElement;
                foreach (XmlNode node in fromRoot.SelectNodes("//Grade"))
                {
                    if (node.ChildNodes[0].Name != "Descriptions")
                    {
                        var trElement = createNode(fromXML);
                        node.InsertBefore(trElement, node.ChildNodes[0]);
    
                    }
    
                }
                fromXML.Save(Console.Out);
            }
    

    【讨论】:

    • 感谢您的解决方案,这对我很有帮助。
    【解决方案3】:

    此方法适用于 n 级数

    private void HandleNode(XmlNode node, XmlDocument xmlDoc)
        {
            if (node.HasChildNodes)
            {
                foreach (XmlNode child in node.ChildNodes)
                {
                    if (node.ChildNodes[0].Name != "Descriptions" && node.Name != "Descriptions")
                    {
                        var trElement = createNode(xmlDoc);
                        node.InsertBefore(trElement, node.ChildNodes[0]);
                    }
                    if (node.Name != "Descriptions")
                        HandleNode(child, xmlDoc);
                }
            }
            else
            {
                var trElement = createNode(xmlDoc);
                node.InsertBefore(trElement, node.ChildNodes[0]);
            }
        }
    

    像这样在 doWork 方法中使用它

    public void doWork(string filePath)
        {
            XmlDocument fromXML;
            fromXML = new XmlDocument();
            fromXML.Load(filePath);
            XmlNode fromRoot = fromXML.DocumentElement;
            foreach (XmlNode node in fromRoot.ChildNodes)
            {
                HandleNode(node, fromXML);
            }
            fromXML.Save(filePath);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      相关资源
      最近更新 更多