[英]Why does my C# Xml code only work when I enumerate variable enumerable
我正在處理格式化 XML 文件的代碼,以便子文件夾節點實際上嵌套在其父節點中。 源 XML 將每個文件夾作為根中的單獨子節點而不是正確的樹,因為您期望它在其主文件夾中具有子文件夾。 這個問題的代碼是關於:
// Load original XML
string sFile = "PathFile";
XmlDocument doc = new XmlDocument();
doc.Load(sFile);
var n = doc.DocumentElement.SelectNodes ("//*"); // Load all nodes into nodelist n
// int nCount = n.Count; // If uncommented code works
foreach(XmlNode x in n)
{ rest of the code }
現在我的代碼可以正常工作,但只是有時,即使在兩次運行之間沒有更改任何內容。 我已將其縮小為:在 Visual Studio 中調試代碼時,如果我只是從頭到尾運行代碼,則會出錯。 如果我中斷並查看 XmlNodelist n 中的屬性(通過將 cursor 懸停在它上面並查看元素計數)它確實有效。 發現這一點后,我添加了
int nCount = n.Count;
行,現在代碼從頭到尾在無人監督的情況下運行。
這里發生了什么,解決這個問題的正確方法是什么? 注意: doc.LoadXml 不適用於此特定文件。
謝謝你的負載,
托馬斯
簡短的回答:因為XmlNodeList
實現的副作用。
XmlNode.SelectNodes()
返回一個XmlNodeList
(從技術上講,一個XPathNodeList
),它是與選擇匹配的節點的“實時列表”(在本例中為 XPath 選擇)。
當您迭代XPathNodeList
或以其他方式訪問它時,它會通過匹配節點,根據需要構建一個內部列表,並根據需要返回它們。
因此,如果您在遍歷節點時嘗試重新排列文檔,這可能會破壞迭代並導致它在您遍歷所有節點之前停止。 當文檔在其下方移動時,迭代基本上是在追逐一個移動的目標。
但是,為了返回Count
屬性的值, XPathNodeList
基本上需要找到每個匹配的節點並對其進行計數,因此它會遍歷整個匹配集並將它們全部放入內部列表中。
public override int Count {
get {
if (! done) {
ReadUntil(Int32.MaxValue);
}
return list.Count;
}
}
我認為這解釋了你所看到的。 當您在進行更改之前訪問Count
屬性時,它會構建整個節點列表,作為副作用,因此當您實際迭代它們時仍然會填充該列表。
當然,依賴這種無證行為是不明智的。
相反,我建議您實際上將XmlNodeList
的內容復制到您自己的列表中,然后對其進行迭代:
string sFile = "PathFile";
XmlDocument doc = new XmlDocument();
doc.Load(sFile);
var allNodes = doc.DocumentElement
.SelectNodes("//*")
.OfType<XmlNode>() // using System.Linq;
.ToList();
foreach (XmlNode x in allNodes)
{
// rest of the code
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.