Как я могу использовать цель Нанта xmlpoke для удаления узла - PullRequest
14 голосов
/ 11 февраля 2009

С учетом следующего xml:

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

Использование XMLPoke со следующим XPath:

rootnode/childnode[arg='b']

Результат (если строка замены пуста):

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

Содержимое дочернего узла было удалено, когда мы фактически хотим удалить сам дочерний узел. Желаемый результат:

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

Childnode должен быть выбран на основе аргумента childnode.

1 Ответ

25 голосов
/ 12 февраля 2009

Я поднимаю руки! Это классический случай неправильного задания вопроса.

Проблема в том, что вы не можете использовать xmlpoke для удаления одного узла. Xmlpoke может использоваться только для редактирования содержимого определенного узла или атрибута. Не существует элегантного способа удаления дочернего узла в соответствии с вопросом, используя только стандартные цели Nant . Это можно сделать, используя некоторые не элегантные манипуляции со строками, используя свойства в Nant, но почему вы хотите?

Лучший способ сделать это - написать простую цель Нанта. Вот тот, который я подготовил ранее:

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

Объедините вышеперечисленное с изменением файла NAnt.exe.config для загрузки пользовательской цели и следующего сценария в файле build :

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

Это удалит дочерний узел с аргументом arg со значением b из target.xml . Что я и хотел в первую очередь!

...