I have an xml like the following:
<return>
<exams>
<remove>
</remove>
<add>
<exam errorCode="0" examRef="1" />
</add>
<add>
<exam errorCode="0" examRef="1" />
<exam errorCode="0" examRef="1" />
</add>
</exams>
</return>
and I am building a utility that can differentiate between each node by its extracting its ancestor hierarchy. eg:
return[0].exams[0].add[0].exam[0] //This indicates the first exam node in the first add element.
return[0].exams[0].add[1].exam[0] //This indicates the first exam node in the second add element.
return[0].exams[0].add[1].exam[1] //This indicates the second exam node in the second add element.
and so on. The code that I have so far is:
private string GetAncestorNodeAsString(XElement el)
{
string ancestorData = string.Empty;
el.Ancestors().Reverse().ToList().ForEach(anc =>
{
if (ancestorData == string.Empty)
{
ancestorData = String.Format("{0}[0]", anc.Name.ToString());
}
else
{
ancestorData = String.Format("{0}.{1}[0]", ancestorData, anc.Name.ToString());
}
});
if (ancestorData == string.Empty)
{
ancestorData = el.Name.ToString();
}
else
{
ancestorData = String.Format("{0}.{1}[0]", ancestorData, el.Name.ToString());
}
return ancestorData;
}
This code returns something like:
return[0].exams[0].add[0].exam[0] //zeros here are hardcoded in the code and I need some mechanism to get the position of each of the element in the xml.
I can build up position of elements like:
var elements = el.Elements().Select((e, index) => new
{
node = e,
position = index
});
but this will only give me position of only immediate child elements within an element. I need to identify all ancestors and its position in the xml.
Can anyone help please?
Here is method which will return index of element:
private int GetElementIndex(XElement e)
{
return e.NodesBeforeSelf().OfType<XElement>().Count(x => x.Name == e.Name);
}
And your modified code. Keep in mind - I use AncestorsAndSelf
to use single loop. Also I avoided creating list of elements. And used StringBuilder
to aggregate result and avoid creation of strings.
private static string GetAncestorNodeAsString(XElement e)
{
return e.AncestorsAndSelf().Reverse()
.Aggregate(
new StringBuilder(),
(sb, a) => sb.AppendFormat("{0}{1}[{2}]",
sb.Length == 0 ? "" : ".", a.Name, GetElementIndex(a)),
sb => sb.ToString());
}
Use a recursive method:
private static string GetAncestorNodeAsString(XElement el)
{
if (el.Parent == null)
return String.Format("{0}[0]", el.Name.LocalName);
else
return String.Format("{0}.{1}[{2}]",
GetAncestorNodeAsString(el.Parent),
el.Name.LocalName,
el.ElementsBeforeSelf().Count(e => e.Name == el.Name));
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.