Nant의 XMLPoke 대상을 사용하여 노드를 제거하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/537988

  •  22-08-2019
  •  | 
  •  

문제

다음 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>

어린이는 차일드 인수에 따라 선택되어야합니다.

도움이 되었습니까?

해결책

나는 내 손을 잡고있다! 이것은 잘못된 질문을하는 전형적인 사례입니다.

문제는 사용할 수 없다는 것입니다 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 가치와 함께 ~에서 target.xml. 내가 처음에 내가 원했던 것입니다!

다른 팁

xmlpeek 값 만 읽습니다.xmlpoke 값 만 설정합니다. 불행히도, Nant에는 AN이 없습니다 xmldelete 직무.

나는 넌트를 만들어이 문제를 해결했다 <target /> Nant 파일에서 프로젝트를 쉽게 재사용 할 수 있습니다.

나는 Nant의 내장을 활용하기로 결정했습니다 <regex />, <echo />, <include /> 그리고 <call /> 작업.

장점 :

  • 정기적 인 표현으로 작동합니다 (단점 참조).
  • XML을 포함한 텍스트와 일치 할 수 있습니다!

단점 :

  • 정규식 문제를 해결 한 적이 있습니까? 그렇다면 이제 또 다른 문제가 있습니다!
  • Nant 파일의 Regex 값 해야 하다 탈출하십시오! (온라인 XML Escaper 도구를 사용하십시오).
<!-- 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