【发布时间】:2014-04-23 08:21:21
【问题描述】:
我需要知道 XDocument 中 XElement 的 xpath,以及命名空间,因为我需要它来稍后在 XDocument 中进行查找。
我目前正在使用来自Get the XPath to an XElement? 的示例,它适用于没有命名空间的文档。但不适用于带有命名空间的 xml 文档,支持这一点的工具并没有给我正确的路径。
例如我有 xml 文档
<?xml version="1.0" encoding="utf-8"?>
<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition">
<AutoRefresh>0</AutoRefresh>
<DataSources>
以下代码将找到/:Report 的路径并在XPathSelectElement 上崩溃
var x = XDocument.Load(@"file.xml");
var path = x.Elements().First().GetAbsoluteXPath();
var element = x.XPathSelectElement(path);
路径应该是怎样的?我手动尝试了“/rd:Report”,但仍然无法选择元素。
扩展名,在其他主题中找到:
public static class XExtensions
{
/// <summary>
/// Get the absolute XPath to a given XElement, including the namespace.
/// (e.g. "/a:people/b:person[6]/c:name[1]/d:last[1]").
/// </summary>
public static string GetAbsoluteXPath(this XElement element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
Func<XElement, string> relativeXPath = e =>
{
int index = e.IndexPosition();
var currentNamespace = e.Name.Namespace;
string name;
if (currentNamespace == null)
{
name = e.Name.LocalName;
}
else
{
string namespacePrefix = e.GetPrefixOfNamespace(currentNamespace);
name = namespacePrefix + ":" + e.Name.LocalName;
}
// If the element is the root, no index is required
return (index == -1) ? "/" + name : string.Format
(
"/{0}[{1}]",
name,
index.ToString()
);
};
var ancestors = from e in element.Ancestors()
select relativeXPath(e);
return string.Concat(ancestors.Reverse().ToArray()) +
relativeXPath(element);
}
/// <summary>
/// Get the index of the given XElement relative to its
/// siblings with identical names. If the given element is
/// the root, -1 is returned.
/// </summary>
/// <param name="element">
/// The element to get the index of.
/// </param>
public static int IndexPosition(this XElement element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
if (element.Parent == null)
{
return -1;
}
int i = 1; // Indexes for nodes start at 1, not 0
foreach (var sibling in element.Parent.Elements(element.Name))
{
if (sibling == element)
{
return i;
}
i++;
}
throw new InvalidOperationException
("element has been removed from its parent.");
}
}
【问题讨论】:
-
方法
.GetAbsoluteXPath()来自哪里。我在任何地方都找不到它 -
@Jehof 我已将其添加到问题中