Search code examples
c#loopsxelement

Loop to iterate up parent nodes until it finds specific tag


What I'm doing is finding a specific value within an XML document and then I want to iterate upwards through each parent until it finds the parent with a specific tag name.

List<XElement> fieldReferences = new List<XElement>();
fieldReferences.AddRange(element.XPathSelectElements(string.Format("descendant::nameValue[@idref='{0}']", fieldName)));
fieldReferences.AddRange(element.XPathSelectElements(string.Format("descendant::nameValue[@value='{0}']", fieldName)));

string parentIterator = ".Parent";
string attributeValue = ".Attribute('id').Value";
string parentElementName = ".Name";
foreach (var value in fieldReferences)
{
    var parentField = string.Format("{0}{1}", parentIterator, parentElementName);
    while (value + parentField != "private" || value + parentField != "public")
        {
            // keep appending .Parent until it finds what it needs
        }
    //var parentField = value.Parent.Parent.Parent.Parent.Attribute("id").Value;
    outputFields.Add(parentField, name.FirstOrDefault());
}

The issue that I'm having is that parentField will always be evaluated as a string so it'll never actually check the .Parent.Name property of value.

I don't work often with C# so I'm sure there's a much easier way to do this so my question is: How can I get my parentField string to evaluate the way I want OR how can I do this in a different way to achieve the same end result?

EDIT: Here's what my xml looks like. The XPAthSelectElement gets the nameValue element and I want to iterate through each parent element until I find the private tag

<private id="I need to iterate upwards through each parent element until I find this one">
    <value>
      <request>
        <nameValues>
          <nameValue idref="I found this" />
          <nameValue value=""/>
        </nameValues>
      </request>
    </value>
  </private>

Solution

  • So you don't actually need to do this many string operations to then go crazy with XPath. Once you found your child target element, you can just use the Parent property on the XElement iteratively until you find the XElement with a private/public tag. So that gives us this code:

    foreach (XElement element in fieldReferences)
    {
        XElement currentElement = element;
        while (currentElement.Parent != null)
        {
            currentElement = currentElement.Parent;
            if (currentElement.Name == "private" || currentElement.Name == "public") {
                outputFields.Add(currentElement, /* not sure what you want here */);
                break;
            }
        }
    }
    

    So currentElement would start out as the element with the nameValue tag from your example. In the while loop, each iteration currentElement changes to its parent node until there is no more parent or currentElement has become a private or a public tag. If the latter is the case, it gets appended to your result.