How can I query an XDocument with a 'path'?
Asked Answered
P

4

25

I would like to query an XDocument object for a given path, (e.g. "/path/to/element/I/want") but I don't know how to proceed.

Penile answered 27/6, 2012 at 10:52 Comment(2)
possible duplicate of how to use XPath with XDocument?Horary
You can see an example selecting different paths, with / without namespace definitions, etc. here: https://mcmap.net/q/73134/-how-do-i-get-an-ixmlnamespaceresolver.Microbalance
H
-2

Something similar to this might work:

var path = "/path/to/element/I/want";
var route = path.Split(new []{'/'}, StringSplitOptions.RemoveEmptyEntries);

XElement result = null;
foreach (var node in route)
{
    if (result == null)
    {
        result = _xmlDocument.Element(node);    
    }
    else
    {
        result = result.Element(node);
    }
}

return result;
Hannan answered 27/6, 2012 at 10:54 Comment(3)
RemoveEmptyEntries is not a good idea, // has a specific meaning in XPath and it's to search all descendants.Affiliate
and the condition result==null will provide odd results too.Moulding
tried to edit. Nothing wrong there with the Split given that has nothing to do with XPathMoulding
A
63

You can use methods from System.Xml.XPath.Extensions to do this.

For example, if you want to select a single element, you would use XPathSelectElement():

var element = doc.XPathSelectElement("/path/to/element/I/want");

The queries don't have to be simple paths like what you described, they use the XPath language.

Affiliate answered 27/6, 2012 at 10:56 Comment(2)
In 4.5, use System.Xml.XPath.Armourer
@Armourer Isn't that exactly what I suggested? And the System.Xml.XPath namespace certainly isn't new in .Net 4.5.Affiliate
L
7

Even though this is a somewhat older post, it should be noted that LINQ-to-XML can be used as an alternative to System.XML.XPath to find elements based on a path within an XDocument

Example:

var results = x.Elements("path").Elements("to").Elements("element").Elements("I").Elements("want").FirstOrDefault();

Note: The LINQ to XML command may need to be altered to accommodate for the actual structure and/or cardinality of the XML.

https://msdn.microsoft.com/en-us/library/bb675156.aspx

Lamond answered 9/3, 2015 at 17:30 Comment(1)
This makes no sense. What is x ? If x is an XContainer then Elements is an IEnumerable of XElement and you cannot chain.Moulding
M
0

Similar to DaveDev but does work, if you do not want to use XPath.

public static class XElementExtensions
{
    public static XElement GetStrictDescendant(this XContainer element, string path)
    {
        // todo guard against null path
        var names = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
        if (names.Length == 0) 
            throw new ArgumentException("Empty path", nameof(path));

        var result = element;
        foreach (var name in names)
        {
            result = result.Element(name);
            if (result == null)
            {
                return null;
            }
        }
        return (XElement)result;
    }
}
Moulding answered 15/3, 2022 at 12:50 Comment(0)
H
-2

Something similar to this might work:

var path = "/path/to/element/I/want";
var route = path.Split(new []{'/'}, StringSplitOptions.RemoveEmptyEntries);

XElement result = null;
foreach (var node in route)
{
    if (result == null)
    {
        result = _xmlDocument.Element(node);    
    }
    else
    {
        result = result.Element(node);
    }
}

return result;
Hannan answered 27/6, 2012 at 10:54 Comment(3)
RemoveEmptyEntries is not a good idea, // has a specific meaning in XPath and it's to search all descendants.Affiliate
and the condition result==null will provide odd results too.Moulding
tried to edit. Nothing wrong there with the Split given that has nothing to do with XPathMoulding

© 2022 - 2024 — McMap. All rights reserved.