كيف يمكنني استخدام هدف Nant's Xmlpoke لإزالة العقدة
سؤال
إعطاء 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]*)\<add.*key=\"AWSProfileName\".*value=\"comsec\".*\/\>(?'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="(?'BEFORE'[\w\s\W]*)\<childnode.*arg="b">(.*?)\<\/childnode\>(?'AFTER'[\w\s\W]*)" />
<call target="RemoveLineFromFile" />
</target>
</project>