如何将新节点添加到xml文件

时间:2017-01-22 17:04:26

标签: c# xml

我正在尝试将节点添加到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

3 个答案:

答案 0 :(得分:2)

您需要递归添加节点,检查代码上的注释以获取更多详细信息。

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);
        }
    }

答案 1 :(得分:0)

如果您只需要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);
        }

答案 2 :(得分:0)

此方法适用于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);
    }