Получение значения XML в C # из пути произвольного ключа - PullRequest
0 голосов
/ 29 августа 2018

У меня есть проект, в котором в настоящее время я реализую поддержку чтения значений из файла XML по произвольному / определяемому пользователем пути в ключах документа.

Например, если документ выглядит так:

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

, тогда пользователь может захотеть получить значение с помощью клавиши name в information/machine.

Есть ли способ, используя XDocument / XPath, чтобы я мог искать значения, которые хочет пользователь, не зная / не кодируя в схеме документа?

Моя первоначальная мысль заключалась в том, чтобы проработать документ с помощью формы рекурсивной функции, использующей элементы XElement, но я чувствую, что должно быть более простое и понятное решение, которое не требует, чтобы я свернул свой собственный код поиска.

Я тоже что-то пробовал в этом направлении

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;

но elem всегда равно нулю. Я предполагаю, что есть проблема с тем, как я определяю свой путь или использую XPathSelectElement, но я еще не решил это.

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Я считаю, что мое решение с использованием XPathSelectElement было правильным, мне просто нужно было добавить строку path/to/key с //.

Следующий код, который я использовал в итоге, делает это и удаляет все пробелы вокруг внешней части значения (в случае, если значение находится на отдельной строке, чем открывающий тег.

// 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();
0 голосов
/ 29 августа 2018
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;
}

это использование методов:

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