如何获取当前XML标记的索引?
示例:
<User>
<Contact>
<Name>Lucas</Name>
</Contact>
<Contact>
<Name>Andre</Name>
</Contact>
...
</User>
我正在尝试下面的代码
foreach (var element2 in doc2.Root.Descendants())
{
String name = element.Name.LocalName;
String value = element.Value;
}
我想知道我是在读第一个<Contact>
标签,还是第二个或第三个......
答案 0 :(得分:5)
使用Select的适当重载将在枚举集合时生成索引。
var userContacts = doc2.Root
.Descendants()
.Where(element => element.Name == "Contact")
.Select((c, i) => new {Contact = c, Index = i});
foreach(var indexedContact in userContacts)
{
// indexedContact.Contact
// indexedContact.Index
}
注意:我添加了.Where,因为.Descendants会递归。
答案 1 :(得分:2)
您可以使用for
语句,然后您将始终知道索引。我假设Descendants()
可用于for语句。
另一种可能性是在foreach
之外创建一个计数变量。
int count = 0
foreach (var element2 in doc2.Root.Descendants())
{
String name = element.Name.LocalName;
String value = element.Value;
count++;
}
答案 2 :(得分:1)
将foreach
循环替换为普通的for
循环:
for (int i = 0; i < doc2.Root.Descendants().Count(); i++)
{
String name = doc2.Root.Descendants()[i].Name.LocalName;
String value = doc2.Root.Descendants()[i].Value;
}
然后使用i
查看您是否正在阅读第一个,第二个,第三个等标签。
如果不使用外部计数器,就无法获取foreach枚举器的索引.AFAIK。
这也提出了一个效率问题,因为你必须在每次循环迭代时处理Descendants方法两次,所以我建议保持一个List代表for循环之外的Descendants,然后像这样使用它:
var desecendants = doc2.Root.Descendants().ToList();
for (int i = 0; i < descendants.Count; i++)
{
String name = descendants[i].Name.LocalName;
String value = descendants[i].Value;
}
答案 3 :(得分:1)
我认为你不能使用foreach,而是尝试使用普通的for循环。
答案 4 :(得分:1)
使用变量作为计数器并将结果放入数组中。这里的问题是,你需要提前知道数组的大小。
int i = 0;
foreach (var element in doc2.Root.Descendants()) {
name[i] = element.Name.LocalName;
value[i] = element.Value;
i++;
}
使用List<T>
你没有这个问题
var list = new List<KeyValuePair<string,string>>();
foreach (var element in doc2.Root.Descendants()) {
list.Append(new KeyValuePair(element.Name.LocalName, element.Value));
}
答案 5 :(得分:0)
要获得当前节点的位置而不使用计数器(如前面的解决方案所指出的那样),您需要编写一个函数来构建当前XmlElement的XPath。唯一的方法是使用父节点和以前的兄弟节点从节点遍历文档。这样,您就可以构建精确的XPath来从文档访问您的节点。这是一个取自here
的样本 public static string GetXPath_UsingPreviousSiblings(this XmlElement element)
{
string path = "/" + element.Name;
XmlElement parentElement = element.ParentNode as XmlElement;
if (parentElement != null)
{
// Gets the position within the parent element, based on previous siblings of the same name.
// However, this position is irrelevant if the element is unique under its parent:
XPathNavigator navigator = parentElement.CreateNavigator();
int count = Convert.ToInt32(navigator.Evaluate("count(" + element.Name + ")"));
if (count > 1) // There's more than 1 element with the same name
{
int position = 1;
XmlElement previousSibling = element.PreviousSibling as XmlElement;
while (previousSibling != null)
{
if (previousSibling.Name == element.Name)
position++;
previousSibling = previousSibling.PreviousSibling as XmlElement;
}
path = path + "[" + position + "]";
}
// Climbing up to the parent elements:
path = parentElement.GetXPath_UsingPreviousSiblings() + path;
}
return path;
}
假设您确实需要它,根据文档大小,它可能是资源密集型的。如果您只需要索引,我建议您使用其他方法之一。