¿Cómo puedo usar el objetivo xmlpoke de Nant para eliminar un nodo
(1)
Dado el siguiente xml:
<rootnode>
<childnode arg="a">Content A</childnode>
<childnode arg="b">Content A</childnode>
</rootnode>
Usando XMLPoke con el siguiente XPath:
rootnode/childnode[arg=''b'']
El resultado (si la cadena de reemplazo está vacía) es:
<rootnode>
<childnode arg="a">Content A</childnode>
<childnode arg="b"></childnode>
</rootnode>
El contenido del nodo childno se ha eliminado cuando realmente queremos eliminar el childnode. El resultado deseado es:
<rootnode>
<childnode arg="a">Content A</childnode>
</rootnode>
El childnode se debe seleccionar según el argumento childnode.
¡Alzo las manos! Este es un caso clásico de hacer la pregunta incorrecta.
El problema es que no puedes usar xmlpoke para eliminar un solo nodo. Xmlpoke solo se puede usar para editar los contenidos de un nodo o atributo específico. No hay una manera elegante de eliminar un nodo secundario según la pregunta utilizando solo los objetivos estándares de Nant . Se puede hacer usando algunas manipulaciones de cadenas poco elegantes usando propiedades en Nant, pero ¿por qué querrías?
La mejor manera de hacerlo es escribir un objetivo simple de Nant. Aquí hay uno que preparé antes:
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 lo anterior con una modificación en el archivo NAnt.exe.config para cargar el destino personalizado y el siguiente script en el archivo de compilación :
<xmlstrip xpath="//rootnode/childnode[@arg = ''b'']" file="target.xml" />
Esto eliminará el childnode con un argumento arg con valor b de target.xml . ¡Qué es lo que realmente quería en primer lugar!