获取当前 XmlReader 位置的“路径”

RX_*_*_RX 5 .net c# xml xpath

我真正喜欢JsonReaderJson.NET 的一点是,你总是知道当前位置的路径JsonReader。例如,我们有一个像这样的json:

{
    "name" :
    {
        "first": "John",
        "last": "Smith"
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我们站立或“John”元素,JsonReader.Path将是“name.first”

有没有办法实现类似的东西XmlReader?也许使用 XPath?例如,我们有一个这样的xml:

<root>
    <name>
        <first>John/<first>
        <last>Smith</last>
    </name>
</root>
Run Code Online (Sandbox Code Playgroud)

我想在站在“John”时获得“/root/name/first”,在站在“Smith”时获得“/root/name/last”

RX_*_*_RX 5

似乎没有办法使用标准 .NET 功能来做到这一点,所以我想出了我自己的类。

internal sealed class XmlReaderWrapperWithPath : IDisposable
{
    private const string DefaultPathSeparator = ".";

    private readonly Stack<string> _previousNames = new Stack<string>();
    private readonly XmlReader _reader;
    private readonly bool _ownsReader;

    public XmlReaderWrapperWithPath(XmlReader reader, bool ownsReader)
    {
        if (reader == null)
        {
            throw new ArgumentNullException("reader");
        }

        _ownsReader = ownsReader;
        _reader = reader;
        PathSeparator = DefaultPathSeparator;
    }

    public bool Read()
    {
        var lastDepth = Depth;
        var lastName = Name;

        if (!_reader.Read())
        {
            return false;
        }

        if (Depth > lastDepth)
        {
            _previousNames.Push(lastName);
        }
        else if (Depth < lastDepth)
        {
            _previousNames.Pop();
        }

        return true;
    }

    public string Name
    {
        get
        {
            return _reader.Name;
        }
    }

    public string Value
    {
        get
        {
            return _reader.Value;
        }
    }

    private int Depth
    {
        get
        {
            return _reader.Depth;
        }
    }

    public string Path
    {
        get
        {
            return string.Join(PathSeparator, _previousNames.Reverse());
        }
    }

    public string PathSeparator { get; set; }

    #region IDisposable

    public void Dispose()
    {
        if (_ownsReader)
        {
            _reader.Dispose();
        }
    } 

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

请注意,此类不形成 XPath(因此没有属性的路径),但这足以满足我的需求。希望这对某人有帮助。


小智 -3

我使用XmlDocumentXmlNode类来处理 xml 数据。在这种情况下,当站在节点上时,您将XmlNode拥有x. 没有这样的方法来获取节点的路径。但这段代码可以做到。

        XmlDocument doc = new XmlDocument();
        doc.LoadXml("<root>" +
                        "<name>" +
                            "<first>John</first>" +
                            "<last>Smith</last>" +
                        "</name>" +
                    "</root>");

        XmlNodeList liste = doc.FirstChild.SelectNodes("*/first");
        XmlNode x = liste[0];   //Some Node
        string path = "";
        while (!x.Name.Equals("document"))
        {
            path = x.Name + "\\" + path;
            x = x.ParentNode;
        }
Run Code Online (Sandbox Code Playgroud)