كيف يمكنني استخدام هدف Nant's 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، ولكن لماذا هل تريد أن؟

أفضل طريقة للقيام بذلك هي كتابة هدف 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 فقط يحدد القيم. لسوء الحظ، لا يملك نانت xmldelete. مهمة.

أنا حل هذه المشكلة عن طريق إنشاء نانت <target /> في ملف Nant، يمكنني إعادة الاستخدام بسهولة بين المشروع.

اخترت الاستفادة من مدمجات نانت <regex />, <echo />, <include /> و <call /> مهام.

مزايا:

  • يعمل مع تعبير منتظم (انظر العيوب).
  • يمكن مطابقة أي نص، بما في ذلك XML!

سلبيات:

  • هل سبق لك حل مشكلة مع Regex؟ إذا كانت الإجابة بنعم، فأنت الآن لديك مشكلة أخرى!
  • قيمة Regex في ملف nant يجب أن تهرب! (استخدم أداة 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