如何以编程方式将XmlNode添加到XmlNodeList

我有一个产品的XmlNodeList,其值被放入表中。 现在,我想在找到某个产品时向列表中添加一个新的XmlNode,以便在同一个循环中,新产品的处理方式与文件中最初的项目相同。 这样,函数的结构不需要更改,只需添加下一个处理的额外节点。 但是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); } 

XmlDocument是其节点的工厂,因此您必须这样做:

 XmlNode newNode = document.CreateNode(XmlNodeType.Element, "product", ""); 

或者它的捷径:

 XmlNode newNode = document.CreateElement("product"); 

然后将新创建的节点添加到其父节点:

 node.ParentNode.AppendChild(newNode); 

如果必须处理添加的节点,则必须明确地执行:节点列表是与搜索条件匹配的节点的快照,然后它将不会动态更新。 只需为添加的节点调用insertIntoTable()

 insertIntoTable(node.ParentNode.AppendChild(newNode)); 

如果您的代码差异很大,您可能需要进行一些重构才能使此过程分为两步(首先搜索要添加的节点然后再处理它们)。 当然,您甚至可以遵循完全不同的方法(例如,将节点从XmlNodeList复制到List,然后将它们添加到两个列表中)。

假设这已足够(并且您不需要重构)让我们将所有内容放在一起:

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

重构

重构时间(如果你有200行function,你真的需要它,远远超过我在这里提出的function)。 第一种方法,即使效率不高:

 var list = productsXml .SelectNodes("/portfolio/products/product") .Cast(); .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 

如果您不喜欢ToList()方法,可以像这样使用ToList()

 var list = productsXml .SelectNodes("/portfolio/products/product") .Cast() .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); } 

请注意,在第二个示例中,必须使用for而不是foreach ,因为您在循环中更改了集合。 请注意,您甚至可以保留原始的XmlNodeList对象...

您不能通过使用父XmlDocument的Create *方法之一直接创建XmlNode,而只能创建子类型(例如元素)。 例如,如果要创建新元素:

 XmlElement el = doc.CreateElement("elementName"); node.ParentNode.InsertAfter(el, node); 

请注意,这不会将元素添加到XmlNodeList列表中,因此不会处理该节点。 因此,在添加节点时应该正确地完成节点的所有必要处理。