如何使用Nant';s xmlpoke目标以删除节点
给定以下xml:如何使用Nant';s xmlpoke目标以删除节点,xml,nant,xmlpoke,Xml,Nant,Xmlpoke,给定以下xml: <rootnode> <childnode arg="a">Content A</childnode> <childnode arg="b">Content A</childnode> </rootnode> 结果(如果替换字符串为空)为: 内容A 当我们实际希望删除childnode本身时,childnode的内容已被删除。预期的结果是: <rootnode> <
<rootnode>
<childnode arg="a">Content A</childnode>
<childnode arg="b">Content A</childnode>
</rootnode>
结果(如果替换字符串为空)为:
内容A
当我们实际希望删除childnode本身时,childnode的内容已被删除。预期的结果是:
<rootnode>
<childnode arg="a">Content A</childnode>
</rootnode>
内容A
必须根据childnode参数选择childnode。我举手!这是问错问题的典型案例 问题是不能使用xmlpoke删除单个节点。Xmlpoke只能用于编辑特定节点或属性的内容。根据问题,仅使用标准Nant目标并没有一种优雅的方法来删除子节点。可以使用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文件的修改结合起来,以在生成文件中加载自定义目标和以下脚本:
这将从target.xml中删除带有参数arg且值为b的childnode。这正是我一开始想要的
xmlpeek
仅读取值。
xmlpoke
仅设置值。
不幸的是,nant没有xmldelete任务
我通过在nant文件中创建一个nant
解决了这个问题,我可以很容易地在项目之间重复使用
我选择利用nant内置的
、
、
和
任务
优势:
- 与正则表达式一起使用(请参见缺点)
- 可以匹配任何文本,包括XML李>
- 你曾经用正则表达式解决过问题吗?如果是,您现在有另一个问题李>
- nant文件中的正则表达式值必须转义!(使用在线xml转义器工具)
下面是如何包括和调用此目标。请记住,所有参数都是全局的,必须在调用目标之前定义
:要修改的文件的路径delete.from.file.path
:与要删除的内容匹配的正则表达式(并定义组之前和之后)delete.from.file.regex
为我节省了一些时间。谢谢你!这对名称空间有用吗?这个答案很好地补充了@Iain的答案。它的优点之一是不需要任何额外的编译和配置。
<rootnode>
<childnode arg="a">Content A</childnode>
</rootnode>
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 );
}
}
}
<xmlstrip xpath="//rootnode/childnode[@arg = 'b']" file="target.xml" />