XPath Version Search

How can I find the node with the maximum version from the following document:

<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>

Ideally, this will be achieved with a single XPath function. Currently, I have two functions that give me the maximum significant value, but I can not move from there.

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

or

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

Cheers, Steve

+3
source share
4 answers

If you are using C #, should it be xpath? For example (edited to support multiple files with the same version - the mentioned plural):

        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"));
        }

Or since 2.0 (from OP comment):

    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);
        }
    }
+1
source

I used xsl: sort to achieve similar stuff. Don't remember the exact syntax, but try this

. , , xsl: sort.

0

The code should be able to run on .Net 2.0, so the LINQ solution, although correct, will not fit the script.

I process the XML in the code and do not perform the conversion, so XSLT is not suitable either.

Greetings

0
source

I have a similar solution for your .Net 2.0, I was just hoping for a good clean version of XPath. This seems to be another area (e.g., bitwise operators) in which XPath simply has no answers.

Greetings

0
source

Source: https://habr.com/ru/post/1702740/


All Articles