Finding element in XDocument?

前端 未结 7 1604
眼角桃花
眼角桃花 2020-12-02 20:02

I have a simple XML


  
    greatest Band
            


        
相关标签:
7条回答
  • 2020-12-02 20:15

    My experience when working with large & complicated XML files is that sometimes neither Elements nor Descendants seem to work in retrieving a specific Element (and I still do not know why).

    In such cases, I found that a much safer option is to manually search for the Element, as described by the following MSDN post:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/3d457c3b-292c-49e1-9fd4-9b6a950f9010/how-to-get-tag-name-of-xml-by-using-xdocument?forum=csharpgeneral

    In short, you can create a GetElement function:

    private XElement GetElement(XDocument doc,string elementName)
    {
        foreach (XNode node in doc.DescendantNodes())
        {
            if (node is XElement)
            {
                XElement element = (XElement)node;
                if (element.Name.LocalName.Equals(elementName))
                    return element;
            }
        }
        return null;
    }
    

    Which you can then call like this:

    XElement element = GetElement(doc,"Band");
    

    Note that this will return null if no matching element is found.

    0 讨论(0)
  • 2020-12-02 20:24

    You should use Root to refer to the root element:

    xmlFile.Root.Elements("Band")
    

    If you want to find elements anywhere in the document use Descendants instead:

    xmlFile.Descendants("Band")
    
    0 讨论(0)
  • 2020-12-02 20:27

    Sebastian's answer was the only answer that worked for me while examining a xaml document. If, like me, you'd like a list of all the elements then the method would look a lot like Sebastian's answer above but just returning a list...

        private static List<XElement> GetElements(XDocument doc, string elementName)
        {
            List<XElement> elements = new List<XElement>();
    
            foreach (XNode node in doc.DescendantNodes())
            {
                if (node is XElement)
                {
                    XElement element = (XElement)node;
                    if (element.Name.LocalName.Equals(elementName))
                        elements.Add(element);
                }
            }
            return elements;
        }
    

    Call it thus:

    var elements = GetElements(xamlFile, "Band");
    

    or in the case of my xaml doc where I wanted all the TextBlocks, call it thus:

    var elements = GetElements(xamlFile, "TextBlock");
    
    0 讨论(0)
  • 2020-12-02 20:30

    The problem is that Elements only takes the direct child elements of whatever you call it on. If you want all descendants, use the Descendants method:

    var query = from c in xmlFile.Descendants("Band")
    
    0 讨论(0)
  • 2020-12-02 20:31

    You can do it this way:

    xml.Descendants().SingleOrDefault(p => p.Name.LocalName == "Name of the node to find")
    

    where xml is a XDocument.

    Be aware that the property Name returns an object that has a LocalName and a Namespace. That's why you have to use Name.LocalName if you want to compare by name.

    0 讨论(0)
  • 2020-12-02 20:32

    Elements() will only check direct children - which in the first case is the root element, in the second case children of the root element, hence you get a match in the second case. If you just want any matching descendant use Descendants() instead:

    var query = from c in xmlFile.Descendants("Band") select c;
    

    Also I would suggest you re-structure your Xml: The band name should be an attribute or element value, not the element name itself - this makes querying (and schema validation for that matter) much harder, i.e. something like this:

    <Band>
      <BandProperties Name ="Doors" ID="222" started="1968" />
      <Description>regular Band<![CDATA[lalala]]></Description>
      <Last>1</Last>
      <Salary>2</Salary>
    </Band>
    
    0 讨论(0)
提交回复
热议问题