/// <summary> /// Construit une requête XPath qui pourrait convenir pour obtenir /// le noeud passé en paramètre. /// Attention: il ne s'agit pas d'obtenir un XPath qui retourne exactement /// ce seul noeud, mais bien de proposer une approximation, la plus /// élégante possible, qui pourra facilement être utilisée par l'utilisateur /// pour créer un Template. /// Dans la mesure du possible le XPath proposé tentera d'être le plus précis /// possible, mais ce n'est pas la priorité. /// </summary> /// <param name="tvi"></param> /// <param name="root">Si non vide, l'expression XPath sera relative par ra</param> /// <return>Une instance de AbstractXPathBuilder qui contient la solution proposée. /// Utiliser la méthode AbstractXPathBuilder.ToString() pour /// obtenir une version "lisible" de cette solution.</return> /// <see cref="AbstractXPathBuilder.ToString()"/> /// <seealso cref="AbstractXPathBuilder"/> public AbstractXPathBuilder SuggestXPathFor(TreeViewItem tvi, string root) { TreeViewItem selected = tvi; object concreteObject = treeViewItems2concreteObjects.GetObjectOf(selected); AbstractXPathBuilder builder = XPathFor(concreteObject, root); return(builder); }
/// <summary> /// Créé une expression XPath qui est adaptée pour trouver /// l'objet passé en paramètre. /// L'expression retournée est la plus simple possible. /// Cette méthode n'est pas "bijective", c'est-à-dire que /// l'XPath retournée pourra donner plusieurs correpondances, /// dont "o" fera partie. /// </summary> /// <param name="target">objet concret que l'expression XPath devra être capable de trouver.</param> /// <param name="startingPoint"">si renseignée, cette expression XPath devra être le point de départ de la construction de l'expression XPath retournée. Sinon, on part de la racine du document</param> /// <returns>Une instance de AbstractXPathBuilder</returns> private AbstractXPathBuilder XPathFor(object target, string startingPoint) { AbstractXPathBuilder xpathDest = CreateXPathBuilder(); xpathDest.Build(target); // Evaluer la possibilité de construire un xpath // relatif à un autre xpath : if (string.IsNullOrEmpty(startingPoint) == false) { // obtenir une liste d'objets concrets à partir // de l'expression "startingPoint": IList <object> startingNodes = Select(startingPoint); // pour sauvegarder la meilleure solution: AbstractXPathBuilder bestPath = null; int bestScore = int.MaxValue; foreach (object startingNode in startingNodes) { // construire un AbstractXPathBuilder, AbstractXPathBuilder xpathStart = CreateXPathBuilder(); // faire un Build() dessus, xpathStart.Build(startingNode); // transformer l'objet xpathForRoot // pour qu'il représente un chemin d'accès // à "target" relatif à "starting point". int score = xpathStart.Goto(xpathDest); if (score < bestScore) { bestScore = score; bestPath = xpathStart; } } if (bestPath != null) { xpathDest = bestPath; } } xpathDest.Optimize(); return(xpathDest); }