How to get all Parent Elements ?

ram_rocks

Active member
Joined
Jun 14, 2021
Messages
27
Programming Experience
1-3
Hello all,

In the below attached image have a root and childNodes. So here I want to first check, if I have a Address element in file, then grab a parent elements and add/append all the address elements to it. if there are no address then leave it.
In the new Xml document I should have Same as output.

I first used GetElementstagbyname(PACKAGE) method to get package (the one below ROOT)
then in Foreach loop iterating over all descendants to find out Address
Now I would like to write a utility function like if Address element is found then get Parents of that particular package

I actually don't want to use multiple foreach loops to iterate over child nodes the below is just a example and I actually have a huge file and my parent elements will be different (for eg: package1 and package 2 the parents for Address element is different).
I am not able to figure it out how to get parent elements

Below is the sample code I tried and its not in good shape as I am still trying.

1625013963074.png


Can anyone please help me out ..
1625012861114.png
 
Please post your code and XML as text in code tags, not as screenshots.
 
C#:
XDocument sample = new XDocument();
XmlNodeList pkg = _xd.GetElementsByTagName("PACKAGE");
XElement element = XElement.Parse(pkg.OuterXml);

List<string> parentList = new List<string>();

foreach (XElement ele in element.DescendantsAndSelf())
{
    if (ele.Name.LocalName == "ADDRESS")
    {
        foreach (XElement pNode in GetParents(ele))
        {
            XElement elements = new XElement(pNode.Name.LocalName);
            if (pNode.HasAttributes)
            {
                XAttribute attribute = new XAttribute(pNode.FirstAttribute.Name, "");
                elements.Add(attribute);
            }
            string elemData = (string)elements;
            parentList.Add(elemData);
        }  
        parentList.Reverse();

        // how to add to Xdoc ?
    }
}

public static IEnumerable<XElement> GetParents(XElement node)
{
    XElement cParent = node.Parent;
    while (cParent != null)
    {
        yield return cParent;
        cParent = cParent.Parent;
    }
}
 
You also may find this very instructional:
 
Why not just use Ancestors() to figure out the parent nodes?
The Ancestors and the Get parents method on the top are same

I wrote something like this
C#:
            XDocument sample = new XDocument();
            XElement element = XElement.Parse(node.OuterXml);
            List<XElement> parentList = new List<XElement>();
            foreach (XElement ele in element.DescendantsAndSelf())
            {
                if (ele.Name.LocalName == "ADDRESS")
                {
                    foreach (XElement el in ele.Ancestors())
                    {
                        XElement elements = new XElement(el.Name.LocalName);
                        if (el.HasAttributes)
                        {
                            XAttribute attribute = new XAttribute(el.FirstAttribute.Name, "");
                            elements.Add(attribute);
                        }

                        parentList.Add(elements);

                        foreach (XElement tag in el.ElementsBeforeSelf())
                        {
                            parentList.Add(tag); //actual list
                        }
                    }
                    parentList.Reverse();
                }
            }
and now here in actual list I have
C#:
{<ELEMENTS />}
{<NAME>EmployeeName</NAME>}
{<PACKAGE />}
{<PACKAGES />}
{<NAME>EmployerName</NAME>}
{<PACKAGE />}
the problem is I am trying to figure out how to get exactly like below as xml structure
1625067636413.png
 
Last edited by a moderator:
Based on what you currently are getting in post #6 you are already partway there. All you need to do is stuff that parentList into a Stack<XElement> and then pop the items off so that you get things is the correct order. Or is there something more subtle about your requirements that you are not telling us, but are expecting us to just implicitly pick-up?

To me it's not really clear what you are trying to accomplish. Yes, it's relatively clear about what you are currently doing because you have shared the code you are currently using -- thanks! Most other posters don't even get that far. What's not clear though is why are you trying to do this? What is the significance of EmployerA, EmployeeB, and Employee_Name? Is there some kind of magic grouping that is suppose to happen? Does the order of the addresses matter? Are you just simply trying to discard the non-<ADDRESS> elements below the <ELEMENTS> elements? What's the significance of your blanking out the first attribute found (e.g. lines 11-15)?
 
Based on what you currently are getting in post #6 you are already partway there. All you need to do is stuff that parentList into a Stack<XElement> and then pop the items off so that you get things is the correct order. Or is there something more subtle about your requirements that you are not telling us, but are expecting us to just implicitly pick-up?

To me it's not really clear what you are trying to accomplish. Yes, it's relatively clear about what you are currently doing because you have shared the code you are currently using -- thanks! Most other posters don't even get that far. What's not clear though is why are you trying to do this? What is the significance of EmployerA, EmployeeB, and Employee_Name? Is there some kind of magic grouping that is suppose to happen? Does the order of the addresses matter? Are you just simply trying to discard the non-<ADDRESS> elements below the <ELEMENTS> elements? What's the significance of your blanking out the first attribute found (e.g. lines 11-15)?
Hi

I have a very huge file with 8 <PACKAGE> nodes (one below ROOT in image on top). I have to go to each and every package (main) and check if I have a address elements in it . if yes then pick up all address elements and discard remaining (means same hierarchy - with parent nodes) . if there are no address in package then leave it

the problem is parent elements are not always same that is why I can't use standard search (I mean like we cant use foreach loop with child nodes search up to certain point <elements>)
the best way I thought is use method getElementsbyTag search for that address and then take that complete node (if address also has child nodes copy that complete node)
 
So what's wrong with just doing a recursive descent through the DOM and pruning away the nodes that you don't want?
 
This example gets all PACKAGE elements, removes those that has no Address descendant, else remove Address siblings that is not Address.
C#:
var doc = XDocument.Load("address.xml");
foreach (var pkg in doc.Descendants("PACKAGE").ToArray())
{
    var adr = pkg.Descendants("Address").FirstOrDefault();
    if (adr == null)
        pkg.Remove(); // has no Address, remove
    else
        adr.Parent.Elements().Where(el => el.Name != "Address").Remove(); // remove all sibling not Address
}
doc.Save("address new.xml");
 
Back
Top Bottom