2010-12-02 14 views
1

Quelle est la meilleure pratique pour créer des x-path avec des paramètres?Xml: meilleure pratique pour créer des x-path avec des paramètres

je dois sélectionner le noeud XML où l'attribut a une valeur exacte, quelque chose comme:

XmlNode node = parentNode.SelectSingleNode(
    string.Format("./field1/field2[@attributeName='{0}']", valueRequired)); 
+0

Le problème que vous avez avec ce type de code est que valueRequired doit être correctement échappé pour s'assurer qu'il ne casse pas la syntaxe XPATH. La proposition de Marc Gravell n'a pas ce problème - bien que je suis un grand fan de XPATH :) –

+0

Nous avons des requêtes SQL paramétrées, mais toujours pas de XPath paramétré ... –

Répondre

0

L'hôte du moteur XPath peut créer des variables qui font partie du contexte. Exemple d'hôte, fournissant cette fonctionnalité est XSLT.

En XSLT on pourrait simplement écrire:

field1/field2[@attributeName=$valueRequired]" 

Une façon de créer des variables XPath et fonctions dans .NET est d'utiliser le XsltContext classe et ses méthodes ResolveVariable() et ResolveFunction()

Une autre chose à retenir: N'insérez jamais aveuglément l'entrée de l'utilisateur dans un "squelette" d'une expression XPath. Soyez conscient de la possibilité pour XPath injection.

+0

+1 Pour la recommandation de liaison variable. Je cherchais un cours mais je ne le trouvais pas. –

2

Cela dépend de valueRequired va jamais avoir une valeur telle que méchante '. Mais pour des valeurs simples, cela devrait fonctionner.

Sinon, LINQ to XML est très agréable:

// where parentNode is XElement 
var node = (from el in parentNode.Elements("field1").Elements("field2") 
      where (string) el.Attribute("attributeName") == valueRequired 
      select el).FirstOrDefault(); 

(remplacer le (string) avec d'autres types que nécessaire)

Voici quelque chose de similaire en utilisant LINQ sur une XmlElement:

var parentNode = node.SelectNodes("./field1/field2[@attributeName]") 
     .Cast<XmlElement>() 
     .Where(el => el.GetAttribute("attributeName") == valueRequired) 
     .FirstOrDefault(); 

L'autre option (sans tout LINQ) est simplement en boucle manuellement avec un foreach.

+0

Est-il possible de faire quelque chose comme ça avec du vieux code XmlDocument ou suggérez-vous de le réécrire à XDocument/XElement? –

+0

@Andrew - Je vais modifier pour montrer quelque chose de similaire avec XmlDocument –

+1

Comment la réponse à "meilleure pratique pour créer x-path avec des paramètres" est ... utiliser LINQ? –

1

Parfois, la notation X-Path est plus courte et plus claire que LINQ, dans ce cas je préférerais utiliser X-Path plutôt que LINQ. Dans votre cas, parce que vous connaissez déjà le type d'attribut, il devrait être facile de décider si vous devez inclure des guillemets ou non.

Vous devriez envisager d'utiliser les éléments de System.Xml.XPath, par les méthodes suivantes:

XmlReader xmlReader = XmlReader.Create(xmlFile); 
XElement xmlRoot = XElement.Load(xmlReader); 
xmlReader.Close(); 
IEnumerable<XElement> nodes = 
    xmlRoot.XPathSelectElements(string.Format("./field1/field2[@attributeName='{0}']", valueRequired)); 
+0

N'est-ce pas inutilement ** plus ** complexe que l'exemple de la question d'origine? Oh, et l'arg à 'XPathSelectElements' est borked (ne compilera pas). –

+0

@ Marc Gravell: merci d'avoir éliminé les guillemets. – ArBR

1

Votre approche est très bien. Vous devriez savoir ce qui peut être dans valueRequired. Si vous ne faites pas confiance à sa source, désinfectez-la comme avec des données non fiables.

, vous n'avez pas besoin de commencer un chemin relatif avec ./, utilisez simplement:

field1/field2[@attributeName='{0}']