C# 如何以编程方式将 XmlNode 添加到 XmlNodeList
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19808150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to programmatically add XmlNode to an XmlNodeList
提问by Serve Laurijssen
I have an XmlNodeList of products whose values are put into a table. Now I want to add a new XmlNode to the list when a certain product is found so that in the same loop the new products is treated the same as the items that are originally in the file. This way the structire of the function does not need to change, just add an extra node that is processed next. But an XmlNode is an abstract class and I cant figure out how to create the new node programatically. Is this possible?
我有一个产品的 XmlNodeList,其值被放入一个表中。现在,我想在找到某个产品时向列表中添加一个新的 XmlNode,以便在同一循环中新产品的处理方式与文件中最初的项目相同。这样函数的structire就不需要改变了,只需要增加一个下一个处理的额外节点即可。但是 XmlNode 是一个抽象类,我无法弄清楚如何以编程方式创建新节点。这可能吗?
XmlNodeList list = productsXml.SelectNodes("/portfolio/products/product");
for (int i = 0; i < list.Count; i++)
{
XmlNode node = list[i];
if (node.Attributes["name"].InnertText.StartsWith("PB_"))
{
XmlNode newNode = ????
list.InsertAfter(???, node);
}
insertIntoTable(node);
}
采纳答案by Adriano Repetti
XmlDocument
is the factory for its nodes so you have to do this:
XmlDocument
是其节点的工厂,因此您必须执行以下操作:
XmlNode newNode = document.CreateNode(XmlNodeType.Element, "product", "");
Or its shortcut:
或者它的快捷方式:
XmlNode newNode = document.CreateElement("product");
Then to add newly created node to its parent:
然后将新创建的节点添加到其父节点:
node.ParentNode.AppendChild(newNode);
If added node must be processed then you have to do it explicitly: node list is a snapshot of nodes that matched search condition then it won't be dynamically updated. Simply call insertIntoTable()
for added node:
如果必须处理添加的节点,则必须明确地进行处理:节点列表是与搜索条件匹配的节点的快照,则不会动态更新。只需调用insertIntoTable()
添加的节点:
insertIntoTable(node.ParentNode.AppendChild(newNode));
If your code is much different you may need little bit of refactoring to make this process a two step batch (first search for nodes to add and then process them all). Of course you may even follow a completely different approach (for example copying nodes from XmlNodeList
to a List and then adding them to both lists).
如果您的代码有很大不同,您可能需要进行一点重构以使此过程成为两步批处理(首先搜索要添加的节点,然后将它们全部处理)。当然,您甚至可以采用完全不同的方法(例如,将节点从XmlNodeList
列表复制到列表,然后将它们添加到两个列表)。
Assuming this is enough (and you do not need refactoring) let's put everything together:
假设这已经足够了(并且您不需要重构)让我们将所有内容放在一起:
foreach (var node in productsXml.SelectNodes("/portfolio/products/product"))
{
if (node.Attributes["name"].InnertText.StartsWith("PB_"))
{
XmlNode newNode = document.CreateElement("product");
insertIntoTable(node.ParentNode.AppendChild(newNode));
}
// Move this before previous IF in case it must be processed
// before added node
insertIntoTable(node);
}
Refactoring
重构
Refactoring time (and if you have a 200 lines function you really need it, much more than what I present here). First approach even if not very efficient:
重构时间(如果你有一个 200 行的函数,你真的需要它,比我在这里介绍的要多得多)。第一种方法即使不是很有效:
var list = productsXml
.SelectNodes("/portfolio/products/product")
.Cast<XmlNode>();
.Where(x.Attributes["name"].InnertText.StartsWith("PB_"));
foreach (var node in list)
node.ParentNode.AppendChild(document.CreateElement("product"));
foreach (var node in productsXml.SelectNodes("/portfolio/products/product"))
insertIntoTable(node); // Or your real code
If you do not like a two passes approach you may use ToList()
like this:
如果你不喜欢两遍的方法,你可以这样使用ToList()
:
var list = productsXml
.SelectNodes("/portfolio/products/product")
.Cast<XmlNode>()
.ToList();
for (int i=0; i < list.Count; ++i)
{
var node = list[i];
if (node.Attributes["name"].InnertText.StartsWith("PB_"))
list.Add(node.ParentNode.AppendChild(document.CreateElement("product"))));
insertIntoTable(node);
}
Please note that in second example the use of for
instead of foreach
is mandatory because you change the collection within the loop. Note that you may even keep your original XmlNodeList
object in place...
请注意,在第二个示例中,使用for
代替foreach
是强制性的,因为您在循环中更改了集合。请注意,您甚至可以将原始XmlNodeList
对象保留在原位...
回答by Markus
You can't create an XmlNode directly, but only the subtypes (e.g. elements) by using one of the Create* methods of the parent XmlDocument. E.g. if you want to create a new element:
您不能直接创建 XmlNode,而只能通过使用父XmlDocument的 Create* 方法之一来创建子类型(例如元素)。例如,如果您想创建一个新元素:
XmlElement el = doc.CreateElement("elementName");
node.ParentNode.InsertAfter(el, node);
Please note that this will not add the element to the XmlNodeList list so the node won't be processed. All necessary processing of the node should therefore be done right when adding the node.
请注意,这不会将元素添加到 XmlNodeList 列表,因此不会处理该节点。因此,应在添加节点时正确完成节点的所有必要处理。