【问题标题】:Getting XPath for node with XmlReader使用 XmlReader 获取节点的 XPath
【发布时间】:2015-09-29 02:12:01
【问题描述】:

如何使用XMLReader获取当前节点的XPath?

例如:

<Employee>
    <Entity>
        <Id>1</Id>
    </Entity>
</Employee>

所以我需要为1 获取XPath,即Employee/Entity/Id。有什么想法吗?

using (var reader = XmlReader.Create(basePath, settings))
{
    while (reader.Read())
    {                   
        if (reader.NodeType == XmlNodeType.Text)
        {
            // need to get xpath of the text node
        }
        else if (reader.NodeType == XmlNodeType.Element)
        {
            // need to get xpath of the current node
        }
     }
 }

【问题讨论】:

  • 您必须跟踪您在其中的元素 - 您可以使用堆栈并在读取每个元素时推送它,并在到达 EndElement 时弹出它。不过,你想做什么?你需要下拉到XmlReader吗?使用像 XDocument 这样的 DOM 会更容易。
  • @CharlesMager,你能提供一些例子吗?
  • XmlReader 不能使用 XPath。
  • @AlexanderPetrov 我需要迭代Xml 中的所有节点,并且需要获取每个节点的XPath?这可以使用XDocument 来完成吗?如果是这样,你能发布一些例子吗?

标签: c# xmlreader xmlnode


【解决方案1】:

我的第一个建议是使用更高级别的 API,例如 LINQ to XML。使用像 XmlReader 这样的低级 API 的唯一原因是用于非常大的文件。使用 LINQ to XML,简单的实现相当简单:

var doc = XDocument.Parse(xml);

foreach (var element in doc.Descendants())
{
    var path = element.AncestorsAndSelf().Select(e => e.Name.LocalName).Reverse();
    var xPath = string.Join("/", path);
}

使用XmlReader 有点复杂,因为您必须随时跟踪元素路径:

using (var reader = XmlReader.Create(basePath, settings))
{
    var elements = new Stack<string>();

    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element:
                if(!reader.IsEmptyElement)
                    elements.Push(reader.LocalName);
                break;
            case XmlNodeType.EndElement:
                elements.Pop();
                break;
            case XmlNodeType.Text:
                path = string.Join("/", elements.Reverse());
                break;
        }
    }
}

这是一个工作演示:https://dotnetfiddle.net/dpOzuL

请注意,虽然这适用于您的简单示例,但这是对 XPath 表达式的非常幼稚的创建,并且并非在所有情况下都有效(例如,当您有多个同名的兄弟姐妹或命名空间位于参与)。

【讨论】:

  • 感谢您的宝贵时间,是否可以使用 xdocument 迭代 xml 中的所有元素,然后使用 xpath?您发布的代码仅适用于问题中的架构
  • @SSS 我已更新以迭代所有元素。目前还不清楚你用这个做什么。如果您想要一个在所有情况下都能获得有效 XPath 的不那么天真的实现,请查看 this question
猜你喜欢
  • 2016-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
相关资源
最近更新 更多