Поиск версии XPath - PullRequest
       13

Поиск версии XPath

3 голосов
/ 05 февраля 2009

Как найти узлы с максимальной версией из следующего документа:

<GateKeeperFiles>
  <File>
    <Name>GateKeeper.exe</Name>
    <Major>2</Major>
    <Minor>1</Minor>
    <Build>1</Build>
    <Revision>6</Revision>
  </File>
  <File>
    <Name>GateKeeper.exe</Name>
    <Major>1</Major>
    <Minor>1</Minor>
    <Build>1</Build>
    <Revision>9</Revision>
  </File>
</GateKeeperFiles>

В идеале это достигается с помощью одной функции XPath. В настоящее время у меня есть две функции, которые дают мне максимальное значение, но я не могу прогрессировать оттуда.

/GateKeeperFiles/File[not (Major <= preceding-sibling::File/Major) and not(Major <= following-sibling::File/Major)]

или

/GateKeeperFiles/File[not(/GateKeeperFiles/File/Major > Major)]

Ура, Стив

Ответы [ 4 ]

1 голос
/ 05 февраля 2009

Если вы используете C #, это должен быть xpath? Например (отредактировано для поддержки нескольких файлов с одинаковой версией - пост упомянул множественное число):

        XDocument doc = XDocument.Parse(xml);
        var nodes =
            from file in doc.Document
                .Element("GateKeeperFiles")
                .Elements("File")
            select new {
                   Node = file,
                   Version = new Version(
                     (int) file.Element("Major"),
                     (int) file.Element("Minor"),
                     (int) file.Element("Build"),
                     (int) file.Element("Revision"))
                   } into tmp
                orderby tmp.Version descending
                select tmp;

        var mostRecentVersion = nodes.Select(x => x.Version).FirstOrDefault();
        var files = nodes.TakeWhile(x => x.Version == mostRecentVersion);

        foreach(var file in files) {
            Console.WriteLine("{0}: {1}",
                file.Version,
                (string)file.Node.Element("Name"));
        }

Или с 2.0 (из комментария ОП):

    static int GetVersion(XmlNode element, string xpath) {
        return int.Parse(element.SelectSingleNode(xpath).InnerText);
    }
    static void Main() {
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xml);

        Version bestVersion = null;
        List<XmlElement> files = new List<XmlElement>();
        foreach (XmlElement file in doc.SelectNodes(
                 "/GateKeeperFiles/File")) {
            Version version = new Version(
                GetVersion(file, "Major"), GetVersion(file, "Minor"),
                GetVersion(file, "Build"), GetVersion(file, "Revision"));
            if (bestVersion == null || version > bestVersion) {
                bestVersion = version;
                files.Clear();
                files.Add(file);
            } else if (version == bestVersion) {
                files.Add(file);
            }
        }
        Console.WriteLine("Version: " + bestVersion);
        foreach (XmlElement file in files) {
            Console.WriteLine(file.SelectSingleNode("Name").InnerText);
        }
    }
0 голосов
/ 05 февраля 2009

У меня есть решение, подобное вашему .Net 2.0, я просто надеялся на хорошую чистую версию XPath. Похоже, это еще одна область (например, побитовые операторы), для которой XPath просто не имеет ответов.

Приветствия

0 голосов
/ 05 февраля 2009

Код должен быть в состоянии работать в .Net 2.0, поэтому решение LINQ, хотя и правильное, не будет соответствовать сценарию.

Я обрабатываю XML в коде и не выполняю преобразование, поэтому XSLT также не подойдет.

Приветствия

0 голосов
/ 05 февраля 2009

Я использовал xsl: sort для достижения подобных вещей. Не помню точный синтаксис, но попробуйте это

После этого выберите первый или последний элемент. Я забыл, каково стандартное поведение сортировки по возрастанию или по убыванию, но вы можете переопределить это с помощью xsl: sort.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...