2009-02-05 9 views
3

Comment puis-je trouver le noeud (s) avec la version maximum du document suivant:XPath Version Recherche

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

Idéalement, ce serait acheived avec une seule fonction XPath. J'ai actuellement deux fonctions qui m'obtiennent la valeur principale max mais je ne peux pas sembler progresser à partir de là.

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

ou

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

Cheers, Steve

+0

BTW - vous pourriez vouloir vérifier que votre approche actuelle est en train de faire numérique (plutôt que alphabétique) commande - à savoir est v12

Répondre

1

Si vous utilisez C#, doit-il être XPath? Par exemple (modifié pour prendre en charge plusieurs fichiers avec la même version - pluriel mentionné post):

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

Ou avec 2.0 (de commentaire OP):

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

J'ai utilisé xsl: sort pour réaliser des choses similaires. Ne me souviens pas la syntaxe exacte mais essayez cette

Après cela, sélectionnez le premier ou le dernier élément. J'ai oublié quel est le comportement par défaut de tri ascendant ou descendant, mais vous pouvez remplacer cela avec xsl: tri.

+0

L'OP ne mentionne pas xslt, mais cela pourrait être une option. La valeur par défaut est ascendant, btw. –

0

Le code devrait pouvoir fonctionner sur .Net 2.0 de sorte que la solution LINQ bien que correcte ne conviendra pas au scénario.

Je suis en train de traiter le code XML en code et de ne pas effectuer de transformation, donc XSLT ne conviendrait pas non plus.

Vive

+0

Édité pour inclure la version 2.0 –

+0

XSLT est également "code" - ajustez votre montre! Avez-vous entendu parler de la classe .NET standard XslCompiledTransform? Savez-vous que XSLT est la meilleure option pour le traitement XML, car le langage XSLT a été spécialement conçu pour le traitement de données XML et arborescentes? Ouvre tes yeux, ne sois pas masohist. –

0

j'ai une solution similaire à votre .Net 2.0 un, j'espérais juste pour une belle version XPath propre. On dirait que c'est un autre domaine (comme les opérateurs bit à bit) que XPath n'a tout simplement pas les réponses.

Vive

+0

Je le pense aussi. –

+0

Cela peut être fait dans une seule expression XPath, même si elle ne sera pas belle et peut être assez inefficace si le moteur XPath n'optimise pas dans le bon sens. –