我有一个产品的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);
}
答案 0 :(得分:14)
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行功能,你真的需要它,远远超过我在这里提出的功能)。第一种方法,即使效率不高:
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
如果您不喜欢双通道方法,可以使用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);
}
请注意,在第二个示例中,必须使用for
而不是foreach
,因为您在循环中更改了集合。请注意,您甚至可以保留原始XmlNodeList
对象...
答案 1 :(得分:2)
您不能使用父XmlDocument的一个Create *方法直接创建XmlNode,而只能创建子类型(例如元素)。例如。如果你想创建一个新元素:
XmlElement el = doc.CreateElement("elementName");
node.ParentNode.InsertAfter(el, node);
请注意,这不会将元素添加到XmlNodeList列表中,因此不会处理该节点。因此,在添加节点时,应该正确地完成节点的所有必要处理。