【问题标题】:How to get absolute xpath by passing the xElement name in XmlDocument or XDocument?如何通过在 XmlDocument 或 XDocument 中传递 xElement 名称来获取绝对 xpath?
【发布时间】:2026-01-23 22:05:04
【问题描述】:

我有一个这样的 xml 文件节点结构

<Employee>
    <EmpId></EmpId>
    <EmpName></EmpName>
    <Salary>
        <Basic></Basic>
        <HRA></HRA>
    </Salary>
    <Qualifications>
        <Course>
            <Name></Name>
            <Year></year>
        </course>
        <Course>
            <Name></Name>
            <Year></year>
        </course>
        <Course>
            <Name></Name>
            <Year></year>
        </course>
    </Qualifications>
<Employee>

从这个文件中,我想使用 XmlDocument 或 XDocument 获取任何给定元素名称(不是 XElement)的绝对 xpath。 怎么做?

【问题讨论】:

    标签: c# .net xml xpath linq-to-xml


    【解决方案1】:

    对于没有命名空间的简单 XML,试试这个:

    public static string GetPath(XElement element)
    {
        return string.Join("/", element.AncestorsAndSelf().Reverse()
            .Select(e =>
                {
                    var index = GetIndex(e);
    
                    if (index == 1)
                    {
                        return e.Name.LocalName;
                    }
    
                    return string.Format("{0}[{1}]", e.Name.LocalName, GetIndex(e));
                }));
    
    }
    
    private static int GetIndex(XElement element)
    {
        var i = 1;
    
        if (element.Parent == null)
        {
            return 1;
        }
    
        foreach (var e in element.Parent.Elements(element.Name.LocalName))
        {
            if (e == element)
            {
                break;
            }
    
            i++;
        }
    
        return i;
    }
    

    【讨论】:

    • Kirill Polishchuk 感谢您的回复。您将 XElement 类型变量作为参数传递给上述代码中的方法,它包含像 30000 这样的值,但在我的情况下,我只会将“Basic”作为字符串传递。如何通过 paasing xElement 获得完整的 xpath名称为字符串?
    • @NareshReddy,如何通过名称确定 XML 元素?在 XML 文档中可以有很多同名的元素。
    • @NareshReddy,无论如何,你可以先找到XElement 的名称,然后将其传递给我提供的方法。
    • 我有一个包含元素名称的列表。使用该列表我将传递每个名称​​。如果它有多个元素,它应该返回第一个元素 xpath。
    • @NareshReddy,您可以使用此代码:var element = doc.Descendants(elemnetName).First();。然后将element 传递给提供的方法。
    【解决方案2】:

    我使用XDocument 类的Descendants 方法实现了:

    XElement xElement = xDocument.Descendants("Basic").First();
    

    在此处将 XML 元素“Basic”作为字符串传递

    public void ConvertObjectToXml(Employee employee )
    {
        MemoryStream Stream = new MemoryStream();
        //To remove the default xml name space
        XmlSerializerNamespaces XmlNS = new XmlSerializerNamespaces();
        XmlNS.Add("", "");
        XmlSerializer XmlSerializer = new XmlSerializer(employee .GetType());
        XmlSerializer.Serialize(Stream, employee , XmlNS);
        Stream.Flush();
        Stream.Seek(0, SeekOrigin.Begin);
        XDocument xDocument = XDocument.Load(Stream);
        //Paasing the "Basic" as string
        XElement xElement = xDocument.Descendants("Basic").First();
        string xpath = GetPath(xElement);
          //Paasing the "Course" as string
        XElement XElement1 =xDocument.Descendants("Course").First();
        string xpath1 = GetPath(XElement1);
    }
    
    public static string GetPath(XElement element)
    {
        return string.Join("/", element.AncestorsAndSelf().Reverse()
            .Select(e => 
            {
                var index = GetIndex(e); 
                if (index == 1) 
                {
                    return e.Name.LocalName; 
                }
                return string.Format("{0}[{1}]", e.Name.LocalName, GetIndex(e)); 
            })); 
    } 
    
    public static int GetIndex(XElement element) 
    {
        var i = 1; 
        if (element.Parent == null) 
        {
            return 1; 
        }
        foreach (var e in element.Parent.Elements(element.Name.LocalName)) 
        {
            if (e == element)
            { 
                break; 
            }
            i++;
        }
        return i; 
    } 
    

    【讨论】: