简体   繁体   English

从任意键路径检索C#中的XML值

[英]Retrieving XML value in C# from arbitary key path

I've got a project where I'm currently implementing support for reading values from an XML file via an arbitrary/user-defined path within the document's keys. 我有一个项目,目前正在实现通过文档键内的任意/用户定义路径从XML文件读取值的支持。

For example, if the document looks like this: 例如,如果文档如下所示:

<information>
    <machine>
        <foo></foo>
        <name>
            test machine
        </name>
        <bar>spam</bar>
    </machine>
</information>

then the user might want to retrieve the value from the name key in information/machine . 那么用户可能想从information/machinename键检索值。

Is there a way using XDocument / XPath that I can look up the values the user wants without knowing/coding in the schema for the document? 有没有一种方法可以使用XDocument / XPath来查找用户想要的值,而无需了解/编码文档的架构?

My initial thought was working through the document with a form of recursive function utilizing XElement items, but I feel like there ought to be a simpler/cleaner solution that doesn't require me rolling my own lookup code. 我最初的想法是通过使用XElement项目的递归函数形式来处理文档,但是我觉得应该有一个更简单/更干净的解决方案,不需要我滚动自己的查找代码。

I also tried something along these lines 我也尝试了这些方法

var doc = XDocument.Load("C:\Path\to\XML\file.xml");

// Split the parent keys string
XElement elem = doc.Root.XPathSelectElement("path/to/key");
if (elem != null && elem.Attribute("wantedKeyName") != null)
    replace = elem.Attribute("wantedKeyName").Value;

but elem is always null. elem始终为空。 I'm assuming there's a problem with the way I'm defining my path or utilizing XPathSelectElement, but I haven't worked it out yet. 我假设我定义路径或使用XPathSelectElement的方式存在问题,但是我还没有解决。

static XmlNode SearchNode(XmlNodeList nodeList, string nodeName)
{
    for (int i = 0; i < nodeList.Count; i++)
    {
        if (nodeList[i].Name == nodeName)
        {
            return nodeList[i];
        }

        if (nodeList[i].HasChildNodes)
        {
            XmlNode node = SearchNode(nodeList[i].ChildNodes, nodeName);
            if (node != null)
            {
                return node;
            }
        }
    }

    return null;
}

static XmlNodeList SearchNodeByPath(XmlNodeList nodeList, string xPath)
{
    for (int i = 0; i < nodeList.Count; i++)
    {
        var nodes = nodeList[i].SelectNodes(xPath);
        if (nodes != null && nodes.Count > 0)
        {
            return nodes;
        }

        if (nodeList[i].HasChildNodes)
        {
            XmlNodeList innerNodes = SearchNodeByPath(nodeList[i].ChildNodes, xPath);
            if (innerNodes != null && innerNodes.Count > 0)
            {
                return innerNodes;
            }
        }
    }

    return null;
}

this is using of methods : 这是使用方法:

    var node = SearchNode(doc.ChildNodes, "compiler");
    var node1 = SearchNodeByPath(doc.ChildNodes, "compilers/compiler");

I turns out my solution using XPathSelectElement was the correct approach, I just had to prepend the path/to/key string with // . 我发现使用XPathSelectElement解决方案是正确的方法,我只需要在path/to/key字符串前加上//

The following code I ended up using does that and strips off any whitespace around the outside of the value (in case the value is on a separate line than the opening tag. 我最终使用的以下代码将执行此操作,并去除了值外部的所有空白(如果值与开始标记不在同一行)。

// xml is a struct with the path to the parent node (path/to/key)
// and the key name to look up
// Split the parent keys string
XElement elem = doc.Root.XPathSelectElement("//" + xml.KeyPath);
if (elem != null && elem.Element(xml.Key) != null)
    replace = elem.Element(xml.Key).Value.Trim();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM