鉴于以下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>

内容childnode已被删除,当我们真正想要的childnode本身删除。所希望的结果是:

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

该childnode的选择必须基于childnode的论点。

有帮助吗?

解决方案

我握住我的手!这是问错了问题的一个典型例子。

的问题是,不能使用 xmlpoke 除去的单个节点。 Xmlpoke 仅可用于编辑的特定节点或属性的内容。没有一种优雅的方式来删除一个子节点按照只使用标准的南特的目标的问题。它的可以使用南特使用属性一些不雅的字符串操作来完成,但是为什么会要?

要做到这一点,最好的方法是编写一个简单的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 文件来加载定制目标和在下面的脚本的构建文件:

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

这将与一个参数的 ARG 与值 B'/ em>的从 target.xml 删除 childnode 。这是我在第一时间其实是想!

其他提示

xmlpeek 只读值。xmlpoke 唯一套价值观。不幸的是,nant没有 xmldelete 任务。

我解决了这个问题通过创建一个nant <target /> 在nant文件,我可以很容易地重新使用之间的项目。

我选择利用nant的内在 <regex />, <echo />, <include /><call /> 任务。

优点:

  • 工作与普通的表达(见缺点).
  • 可以配任何案文,包括XML!

缺点:

  • 你有没有解决的一个问题regex?如果是的话,你现在你拥有的另一个问题!
  • Regex值在nant文件 必须 可以逃脱!(使用一个在线xml逃避者工具)。
<!-- This file should be included before being called -->
<project name="YourProject">

    <target name="RemoveLineFromFile">

        <loadfile 
            file="${delete.from.file.path}" 
            property="xml.file.content" />
        <property 
            name="delete.from.file.regex" 
            value="(?'BEFORE'[\w\s\W]*)\&lt;add.*key=\&quot;AWSProfileName\&quot;.*value=\&quot;comsec\&quot;.*\/\&gt;(?'AFTER'[\w\s\W]*)" />
        <regex 
          input="${xml.file.content}" 
          pattern="${delete.from.file.regex}" />
        <echo 
          file="${delete.from.file.path}"
          message="${BEFORE}${AFTER}"
          append="false" />

    </target>

</project>

下面是如何为包括并呼吁这一目标。铭记所有的参数是全球性的,必须定义 之前 叫目标。

  • delete.from.file.path:路径的文件被修改。
  • delete.from.file.regex:regex匹配怎么删除(和定义前后组)。
<project name="YourProject">

    <include buildfile="path\to\nant\target\RemoveLineFromFile.build"/>

    <target name="OtherWork">

        <property name="delete.from.file.path" value="path\to\xml\file.xml" />
        <property name="delete.from.file.regex" value="(?&apos;BEFORE&apos;[\w\s\W]*)\&lt;childnode.*arg=&quot;b&quot;&gt;(.*?)\&lt;\/childnode\&gt;(?&apos;AFTER&apos;[\w\s\W]*)" />
        <call target="RemoveLineFromFile" />

    </target>

</project>

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top