2009-02-11 5 views
13

Vu le code XML suivant:Comment puis-je utiliser la cible de xmlpoke de Nant pour supprimer un nœud

<rootnode> 
    <childnode arg="a">Content A</childnode> 
    <childnode arg="b">Content A</childnode> 
</rootnode> 

En utilisant XMLPoke avec le XPath suivant:

rootnode/childnode[arg='b'] 

Le résultat (si la chaîne de remplacement est vide) est:

<rootnode> 
    <childnode arg="a">Content A</childnode> 
    <childnode arg="b"></childnode> 
</rootnode> 

Le contenu du childnode a été supprimé lorsque nous voulons réellement l'enfantno de lui-même enlevé. Le résultat souhaité est:

<rootnode> 
    <childnode arg="a">Content A</childnode> 
</rootnode> 

Le nœud enfant doit être sélectionné en fonction de l'argument childnode.

Répondre

24

Je me lève les mains! C'est un cas classique de poser la mauvaise question.

Le problème est que vous ne pouvez pas utiliser xmlpoke pour supprimer un seul nœud. Xmlpoke ne peut être utilisé que pour modifier le contenu d'un noeud ou d'un attribut spécifique. Il n'y a pas une façon élégante de supprimer un nœud enfant selon la question en utilisant uniquement les cibles Nant standard. Il peut être fait en utilisant une manipulation de chaîne inélégant en utilisant les propriétés de Nant, mais pourquoi voulez-vous?

La meilleure façon d'y parvenir est d'écrire une cible Nant simple. Voilà que je préparais plus tôt:

using System; 
using System.IO; 
using System.Xml; 
using NAnt.Core; 
using NAnt.Core.Attributes; 

namespace XmlStrip 
{ 
    [TaskName("xmlstrip")] 
    public class XmlStrip : Task 
    { 
     [TaskAttribute("xpath", Required = true), StringValidator(AllowEmpty = false)] 
     public string XPath { get; set; } 

     [TaskAttribute("file", Required = true)] 
     public FileInfo XmlFile { get; set; } 

     protected override void ExecuteTask() 
     { 
      string filename = XmlFile.FullName; 
      Log(Level.Info, "Attempting to load XML document in file '{0}'.", filename); 
      XmlDocument document = new XmlDocument(); 
      document.Load(filename); 
      Log(Level.Info, "XML document in file '{0}' loaded successfully.", filename); 

      XmlNode node = document.SelectSingleNode(XPath); 
      if(null == node) 
      { 
       throw new BuildException(String.Format("Node not found by XPath '{0}'", XPath)); 
      } 

      node.ParentNode.RemoveChild(node); 

      Log(Level.Info, "Attempting to save XML document to '{0}'.", filename); 
      document.Save(filename); 
      Log(Level.Info, "XML document successfully saved to '{0}'.", filename); 
     } 
    } 
} 

Combine ci-dessus avec une modification du fichier NAnt.exe.config pour charger la cible personnalisée et le script suivant dans le fichier build:

<xmlstrip xpath="//rootnode/childnode[@arg = 'b']" file="target.xml" /> 

Cela supprime le childNode avec un argument arg avec la valeur b de target.xm l. C'est ce que je voulais vraiment en premier lieu!

+1

M'avait fait gagner du temps. Merci pour cela! – aleemb

+1

Merci d'avoir posté la source. –

Questions connexes