保持仅包含特定字符串值

时间:2017-05-27 20:36:48

标签: c# xml console-application

我是新来的,如果我做错了,请原谅。

我有一系列具有不同XML节点定义的不同XML文档。我正在尝试创建一个实用的控制台应用程序,它允许我将任何xml文件修剪为包含其中特定字符串值的节点。

例如这个xml:

<CWeaponInfoBlob>
    <SlotNavigateOrder>
        <Item>
            <WeaponSlots>
                <Item>
                    <OrderNumber value="10" />
                    <Entry>SLOT_UNARMED</Entry>
                </Item>
                <Item>
                    <OrderNumber value="20" />
                    <Entry>SLOT_KNIFE</Entry>
                </Item>
                <Item>
                    <OrderNumber value="30" />
                    <Entry>SLOT_NIGHTSTICK</Entry>
                </Item>
                <Item>
                    <OrderNumber value="40" />
                    <Entry>SLOT_HAMMER</Entry>
                </Item>
                <Item>
                    <OrderNumber value="50" />
                    <Entry>SLOT_BAT</Entry>
                </Item>
                <Item>
                    <OrderNumber value="60" />
                    <Entry>SLOT_CROWBAR</Entry>
                </Item>
                <Item>
                    <OrderNumber value="70" />
                    <Entry>SLOT_GOLFCLUB</Entry>
                </Item>
                <Item>
                    <OrderNumber value="90" />
                    <Entry>SLOT_PISTOL</Entry>
                </Item>
                <Item>
                    <OrderNumber value="100" />
                    <Entry>SLOT_COMBATPISTOL</Entry>
                </Item>
                <Item>
                    <OrderNumber value="110" />
                    <Entry>SLOT_PISTOL50</Entry>
                </Item>
                <Item>
                    <OrderNumber value="120" />
                    <Entry>SLOT_APPISTOL</Entry>
                </Item>
                <Item>
                    <OrderNumber value="130" />
                    <Entry>SLOT_STUNGUN</Entry>
                </Item>
            </WeaponSlots>
        </Item>
    </SlotNavigationOrder>
</CWeaponInfoBlob>

我希望能够像“STUNGUN”一样将字符串传递给控制台,并让程序删除任何不包含该字的“Item”节点。

我已经成功完成了这项工作,但并不像我希望的那样。我有一个包含21,615行的XML文件,其中包含“武器”的定义。通过将“STUNGUN”传递给控制台,我希望它能做同样的事情,并删除没有包含输入单词的节点的任何节点(我猜父节点)。

Here's my xml file 如果你搜索单词“STUNGUN”,你会发现它的多个定义,我希望程序只保留那些节点(和兄弟节点!! )。我该怎么做呢?

这是我尝试过的(不要判断代码,我在5年的编程中从未做过这样的事情,显然它不起作用):

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace XmlUtil
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length <= 0)
                return;

            if (!args.All(i => i.EndsWith(".meta")) && !args.All(i => i.EndsWith(".xml")))
                return;

            try
            {
                for (int x = 0; x < args.Length; x++)
                {
                    var arg = args[x];

                    Console.WriteLine("Enter a string value:");
                    var userInput = Console.ReadLine();

                    var xml = new XmlDocument();
                    xml.Load(arg);
                    var nodes = xml.GetElementsByTagName("*");
                    var ienum = nodes.GetEnumerator();

                    XmlDocument newDoc = new XmlDocument();
                    while(ienum.MoveNext())
                    {
                        XmlNode node = (XmlNode)ienum.Current;
                        if (node.InnerText.Contains(userinput))
                        {
                            newDoc.ImportNode(node, false);
                        }
                    }
                    // Then write it to a file...
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
                Console.ReadLine();
            }

            Console.WriteLine("Press [Enter] to exit...");
            Console.ReadLine();
        }
    }
}

编辑:我想补充一点,这是手动完成的,我花了几个小时来剪掉不需要的节点。

<?xml version="1.0" encoding="UTF-8"?>
<CWeaponInfoBlob>
    <SlotNavigateOrder>
        <Item>
            <WeaponSlots>
                <Item>
                    <OrderNumber value="191" />
                    <Entry>SLOT_SCICARBINE</Entry>
                </Item>
            </WeaponSlots>
        </Item>
        <Item>
            <WeaponSlots>
                <Item>
                    <OrderNumber value="201" />
                    <Entry>SLOT_SCICARBINE</Entry>
                </Item>
            </WeaponSlots>
        </Item>
    </SlotNavigateOrder>
    <SlotBestOrder>
        <WeaponSlots>
            <Item>
                <OrderNumber value="81" />
                <Entry>SLOT_SCICARBINE</Entry>
            </Item>
        </WeaponSlots>
    </SlotBestOrder>
    <TintSpecValues />
    <FiringPatternAliases />
    <UpperBodyFixupExpressionData />
    <AimingInfos />
    <Infos>
        <Item>
            <Infos>
                <Item type="CWeaponInfo">
                    <Name>WEAPON_SCICARBINE</Name>
                    <Model>W_AR_SCICARBINERIFLE</Model>
                    <Audio>AUDIO_ITEM_RAILGUN</Audio>
                    <Slot>SLOT_SCICARBINE</Slot>
                    <DamageType>BULLET</DamageType>
                    <Explosion>
                        <Default>DONTCARE</Default>
                        <HitCar>DONTCARE</HitCar>
                        <HitTruck>DONTCARE</HitTruck>
                        <HitBike>DONTCARE</HitBike>
                        <HitBoat>DONTCARE</HitBoat>
                        <HitPlane>DONTCARE</HitPlane>
                    </Explosion>
                    <FireType>INSTANT_HIT</FireType>
                    <WheelSlot>WHEEL_RIFLE</WheelSlot>
                    <Group>GROUP_RIFLE</Group>
                    <AmmoInfo ref="AMMO_RIFLE" />
                    <AimingInfo ref="RIFLE_LO_BASE_STRAFE" />
                    <ClipSize value="30" />
                    <AccuracySpread value="3.000000" />
                    <AccurateModeAccuracyModifier value="0.500000" />
                    <RunAndGunAccuracyModifier value="2.000000" />
                    <RunAndGunAccuracyMaxModifier value="1.000000" />
                    <RecoilAccuracyMax value="0.500000" />
                    <RecoilErrorTime value="3.000000" />
                    <RecoilRecoveryRate value="1.000000" />
                    <RecoilAccuracyToAllowHeadShotAI value="1000.000000" />
                    <MinHeadShotDistanceAI value="1000.000000" />
                    <MaxHeadShotDistanceAI value="1000.000000" />
                    <HeadShotDamageModifierAI value="1000.000000" />
                    <RecoilAccuracyToAllowHeadShotPlayer value="0.175000" />
                    <MinHeadShotDistancePlayer value="5.000000" />
                    <MaxHeadShotDistancePlayer value="40.000000" />
                    <HeadShotDamageModifierPlayer value="18.000000" />
                    <Damage value="32.000000" />
                    <DamageTime value="0.000000" />
                    <DamageTimeInVehicle value="0.000000" />
                    <DamageTimeInVehicleHeadShot value="0.000000" />
                    <HitLimbsDamageModifier value="0.500000" />
                    <NetworkHitLimbsDamageModifier value="0.800000" />
                    <LightlyArmouredDamageModifier value="0.750000" />
                    <Force value="75.000000" />
                    <ForceHitPed value="140.000000" />
                    <ForceHitVehicle value="1200.000000" />
                    <ForceHitFlyingHeli value="1250.000000" />
                    <OverrideForces>
                        <Item>
                            <BoneTag>BONETAG_HEAD</BoneTag>
                            <ForceFront value="80.000000" />
                            <ForceBack value="50.000000" />
                        </Item>
                        <Item>
                            <BoneTag>BONETAG_NECK</BoneTag>
                            <ForceFront value="60.000000" />
                            <ForceBack value="90.000000" />
                        </Item>
                        <Item>
                            <BoneTag>BONETAG_L_THIGH</BoneTag>
                            <ForceFront value="40.000000" />
                            <ForceBack value="1.000000" />
                        </Item>
                        <Item>
                            <BoneTag>BONETAG_R_THIGH</BoneTag>
                            <ForceFront value="40.000000" />
                            <ForceBack value="1.000000" />
                        </Item>
                        <Item>
                            <BoneTag>BONETAG_L_CALF</BoneTag>
                            <ForceFront value="70.000000" />
                            <ForceBack value="80.000000" />
                        </Item>
                        <Item>
                            <BoneTag>BONETAG_R_CALF</BoneTag>
                            <ForceFront value="60.000000" />
                            <ForceBack value="100.000000" />
                        </Item>
                    </OverrideForces>
                    <ForceMaxStrengthMult value="1.000000" />
                    <ForceFalloffRangeStart value="0.000000" />
                    <ForceFalloffRangeEnd value="50.000000" />
                    <ForceFalloffMin value="1.000000" />
                    <ProjectileForce value="0.000000" />
                    <FragImpulse value="600.000000" />
                    <Penetration value="0.100000" />
                    <VerticalLaunchAdjustment value="0.000000" />
                    <DropForwardVelocity value="0.000000" />
                    <Speed value="2000.000000" />
                    <BulletsInBatch value="1" />
                    <BatchSpread value="0.000000" />
                    <ReloadTimeMP value="-1.000000" />
                    <ReloadTimeSP value="-1.000000" />
                    <VehicleReloadTime value="1.000000" />
                    <AnimReloadRate value="1.000000" />
                    <BulletsPerAnimLoop value="1" />
                    <TimeBetweenShots value="0.135000" />
                    <TimeLeftBetweenShotsWhereShouldFireIsCached value="-1.000000" />
                    <SpinUpTime value="0.000000" />
                    <SpinTime value="0.000000" />
                    <SpinDownTime value="0.000000" />
                    <AlternateWaitTime value="-1.000000" />
                    <BulletBendingNearRadius value="0.000000" />
                    <BulletBendingFarRadius value="0.750000" />
                    <BulletBendingZoomedRadius value="0.375000" />
                    <FirstPersonBulletBendingNearRadius value="0.000000" />
                    <FirstPersonBulletBendingFarRadius value="0.750000" />
                    <FirstPersonBulletBendingZoomedRadius value="0.375000" />
                    <Fx>
                        <EffectGroup>WEAPON_EFFECT_GROUP_RIFLE_ASSAULT</EffectGroup>
                        <FlashFx>muz_railgun</FlashFx>
                        <FlashFxAlt />
                        <FlashFxFP />
                        <FlashFxAltFP />
                        <MuzzleSmokeFx />
                        <MuzzleSmokeFxFP />
                        <MuzzleSmokeFxMinLevel value="0.000000" />
                        <MuzzleSmokeFxIncPerShot value="0.000000" />
                        <MuzzleSmokeFxDecPerSec value="0.000000" />
                        <ShellFx>eject_auto</ShellFx>
                        <ShellFxFP>eject_auto_fp</ShellFxFP>
                        <TracerFx>bullet_tracer</TracerFx>
                        <PedDamageHash>BulletLarge</PedDamageHash>
                        <TracerFxChanceSP value="0.150000" />
                        <TracerFxChanceMP value="0.750000" />
                        <FlashFxChanceSP value="1.000000" />
                        <FlashFxChanceMP value="1.000000" />
                        <FlashFxAltChance value="0.200000" />
                        <FlashFxScale value="1.000000" />
                        <FlashFxLightEnabled value="true" />
                        <FlashFxLightCastsShadows value="false" />
                        <FlashFxLightOffsetDist value="0.000000" />
                        <FlashFxLightRGBAMin x="255.000000" y="93.000000" z="25.000000" />
                        <FlashFxLightRGBAMax x="255.000000" y="100.000000" z="50.000000" />
                        <FlashFxLightIntensityMinMax x="1.000000" y="2.000000" />
                        <FlashFxLightRangeMinMax x="2.500000" y="3.500000" />
                        <FlashFxLightFalloffMinMax x="1024.000000" y="1536.000000" />
                        <GroundDisturbFxEnabled value="false" />
                        <GroundDisturbFxDist value="5.000000" />
                        <GroundDisturbFxNameDefault />
                        <GroundDisturbFxNameSand />
                        <GroundDisturbFxNameDirt />
                        <GroundDisturbFxNameWater />
                        <GroundDisturbFxNameFoliage />
                    </Fx>
                    <InitialRumbleDuration value="90" />
                    <InitialRumbleIntensity value="0.700000" />
                    <InitialRumbleIntensityTrigger value="0.950000" />
                    <RumbleDuration value="90" />
                    <RumbleIntensity value="0.100000" />
                    <RumbleIntensityTrigger value="0.800000" />
                    <RumbleDamageIntensity value="1.000000" />
                    <InitialRumbleDurationFps value="150" />
                    <InitialRumbleIntensityFps value="1.000000" />
                    <RumbleDurationFps value="95" />
                    <RumbleIntensityFps value="1.000000" />
                    <NetworkPlayerDamageModifier value="1.000000" />
                    <NetworkPedDamageModifier value="1.000000" />
                    <NetworkHeadShotPlayerDamageModifier value="1.700000" />
                    <LockOnRange value="65.000000" />
                    <WeaponRange value="120.000000" />
                    <BulletDirectionOffsetInDegrees value="0.000000" />
                    <AiSoundRange value="-1.000000" />
                    <AiPotentialBlastEventRange value="-1.000000" />
                    <DamageFallOffRangeMin value="47.500000" />
                    <DamageFallOffRangeMax value="120.000000" />
                    <DamageFallOffModifier value="0.300000" />
                    <VehicleWeaponHash />
                    <DefaultCameraHash>DEFAULT_THIRD_PERSON_PED_AIM_CAMERA</DefaultCameraHash>
                    <CoverCameraHash>DEFAULT_THIRD_PERSON_PED_AIM_IN_COVER_CAMERA</CoverCameraHash>
                    <CoverReadyToFireCameraHash />
                    <RunAndGunCameraHash>DEFAULT_THIRD_PERSON_PED_RUN_AND_GUN_CAMERA</RunAndGunCameraHash>
                    <CinematicShootingCameraHash>DEFAULT_THIRD_PERSON_PED_CINEMATIC_SHOOTING_CAMERA</CinematicShootingCameraHash>
                    <AlternativeOrScopedCameraHash />
                    <RunAndGunAlternativeOrScopedCameraHash />
                    <CinematicShootingAlternativeOrScopedCameraHash />
                    <CameraFov value="35.000000" />
                    <FirstPersonScopeFov value="20.00000"/>
                    <FirstPersonScopeAttachmentFov value="20.00000"/>
                    <FirstPersonRNGOffset x="0.000000" y="0.000000" z="0.000000" />
                    <FirstPersonRNGRotationOffset x="0.000000" y="0.000000" z="0.000000" />
                    <FirstPersonLTOffset x="0.000000" y="0.000000" z="0.000000" />
                    <FirstPersonLTRotationOffset x="0.000000" y="0.000000" z="0.000000" />
                    <FirstPersonScopeOffset x="0.00000" y="-0.0200" z="-0.0230" />
                    <FirstPersonScopeAttachmentOffset x="0.00000" y="0.0000" z="-0.0280" />
                    <FirstPersonScopeRotationOffset x="-0.70000" y="0.0000" z="0.0000" />
                    <FirstPersonScopeAttachmentRotationOffset x="0.00000" y="0.0000" z="0.0000" />
                    <FirstPersonAsThirdPersonIdleOffset x="-0.07500000" y="0.000000" z="-0.05" />
                    <FirstPersonAsThirdPersonRNGOffset x="-0.025000" y="0.000000" z="-0.075000" />
                    <FirstPersonAsThirdPersonLTOffset x="0.025000" y="0.000000" z="-0.0750000" />
                    <FirstPersonAsThirdPersonScopeOffset x="0.075000" y="-0.050000" z="-0.060000" />
                    <FirstPersonAsThirdPersonWeaponBlockedOffset x="-0.1000000" y="0.000000" z="-0.100000" />
                    <FirstPersonDofSubjectMagnificationPowerFactorNear value="1.025000" />
                    <FirstPersonDofMaxNearInFocusDistance value="0.000000" />
                    <FirstPersonDofMaxNearInFocusDistanceBlendLevel value="0.300000" />
                    <ZoomFactorForAccurateMode value="1.300000" />
                    <RecoilShakeHash>ASSAULT_RIFLE_RECOIL_SHAKE</RecoilShakeHash>
                    <RecoilShakeHashFirstPerson>FPS_ASSAULT_RIFLE_RECOIL_SHAKE</RecoilShakeHashFirstPerson>
                    <AccuracyOffsetShakeHash>DEFAULT_THIRD_PERSON_ACCURACY_OFFSET_SHAKE</AccuracyOffsetShakeHash>
                    <MinTimeBetweenRecoilShakes value="100" />
                    <RecoilShakeAmplitude value="0.333000" />
                    <ExplosionShakeAmplitude value="-1.000000" />
                    <ReticuleHudPosition x="0.000000" y="0.000000" />
                    <AimOffsetMin x="0.250000" y="0.200000" z="0.600000" />
                    <AimProbeLengthMin value="0.430000" />
                    <AimOffsetMax x="0.165000" y="-0.180000" z="0.470000" />
                    <AimProbeLengthMax value="0.340000" />
                    <AimOffsetMinFPSIdle x="0.162000" y="0.225000" z="0.052000" />
                    <AimOffsetMedFPSIdle x="0.187000" y="0.197000" z="0.321000" />
                    <AimOffsetMaxFPSIdle x="0.155000" y="0.038000" z="0.364000" />
                    <AimOffsetEndPosMinFPSIdle x="-0.284000" y="0.612000" z="-0.205000" />
                    <AimOffsetEndPosMedFPSIdle x="-0.178000" y="0.639000" z="0.616000" />
                    <AimOffsetEndPosMaxFPSIdle x="-0.21700" y="-0.096000" z="0.887000" />
                    <AimOffsetMinFPSLT x="0.180000" y="0.231000" z="0.669000" />
                    <AimOffsetMaxFPSLT x="0.048000" y="-0.225000" z="0.409000" />
                    <AimOffsetMinFPSRNG x="0.120000" y="0.275000" z="0.509000" />
                    <AimOffsetMaxFPSRNG x="0.138000" y="-0.212000" z="0.518000" />
                    <AimOffsetMinFPSScope x="0.090000" y="0.078000" z="0.531000" />
                    <AimOffsetMaxFPSScope x="0.006000" y="-0.059000" z="0.694000" />
                    <TorsoAimOffset x="-1.000000" y="0.550000" />
                    <TorsoCrouchedAimOffset x="0.100000" y="0.120000" />
                    <LeftHandIkOffset x="0.230000" y="-0.001000" z="-0.052000" />
                    <ReticuleMinSizeStanding value="0.600000" />
                    <ReticuleMinSizeCrouched value="0.500000" />
                    <ReticuleScale value="0.300000" />
                    <ReticuleStyleHash>WEAPONTYPE_RIFLE</ReticuleStyleHash>
                    <FirstPersonReticuleStyleHash />
                    <PickupHash>PICKUP_WEAPON_SCICARBINE</PickupHash>
                    <MPPickupHash>PICKUP_AMMO_BULLET_MP</MPPickupHash>
                    <HumanNameHash>WT_RIFLE_CBN</HumanNameHash>
                    <MovementModeConditionalIdle>MMI_2Handed</MovementModeConditionalIdle>
                    <StatName>CRBNRIFLE</StatName>
                    <KnockdownCount value="-1" />
                    <KillshotImpulseScale value="1.000000" />
                    <NmShotTuningSet>Automatic</NmShotTuningSet>
                    <AttachPoints>
                                            <Item>
                                                <AttachBone>WAPClip</AttachBone>
                                                <Components>
                                                    <Item>
                                                        <Name>COMPONENT_SCICARBINE_CLIP_01</Name>
                                                        <Default value="true" />
                                                    </Item>
                                                </Components>
                                            </Item>
                                        </AttachPoints>
                    <GunFeedBone />
                    <TargetSequenceGroup />
                    <WeaponFlags>CarriedInHand Automatic Gun CanLockonOnFoot CanLockonInVehicle CanFreeAim TwoHanded AnimReload AnimCrouchFire UsableOnFoot UsableInCover AllowEarlyExitFromFireAnimAfterBulletFired NoLeftHandIKWhenBlocked AllowCloseQuarterKills HasLowCoverReloads HasLowCoverSwaps LongWeapon UseFPSAimIK UseFPSSecondaryMotion</WeaponFlags>
                    <TintSpecValues ref="TINT_DEFAULT" />
                    <FiringPatternAliases ref="FIRING_PATTERN_RIFLE" />
                    <ReloadUpperBodyFixupExpressionData ref="default" />
                    <AmmoDiminishingRate value="3" />
                    <AimingBreathingAdditiveWeight value="1.000000" />
                    <FiringBreathingAdditiveWeight value="1.000000" />
                    <StealthAimingBreathingAdditiveWeight value="1.000000" />
                    <StealthFiringBreathingAdditiveWeight value="1.000000" />
                    <AimingLeanAdditiveWeight value="1.000000" />
                    <FiringLeanAdditiveWeight value="1.000000" />
                    <StealthAimingLeanAdditiveWeight value="1.000000" />
                    <StealthFiringLeanAdditiveWeight value="1.000000" />
                    <ExpandPedCapsuleRadius value="0.000000" />
                    <AudioCollisionHash />
                    <HudDamage value="32" />
                    <HudSpeed value="65" />
                    <HudCapacity value="40" />
                    <HudAccuracy value="55" />
                    <HudRange value="45" />
                </Item>
            </Infos>
        </Item>
    </Infos>
</CWeaponInfoBlob>

请注意,<Item type="CWeaponInfo">的{​​{1}}尚未删除,因为它有一个包含单词SCICARBINE的节点,所以它和它的兄弟姐妹一起保存。

2 个答案:

答案 0 :(得分:1)

将xml linq用于第一个请求

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            XDocument doc = XDocument.Load(FILENAME);

            List<XElement> removeNodes = doc.Descendants("WeaponSlots").Descendants("Item").Where(x => !x.Descendants("Entry").Where(y => (string)y == "SLOT_STUNGUN").Any()).ToList();
            foreach (XElement removeNode in removeNodes)
            {
                removeNode.Remove();
            }

        }
    }
}

第二次请求

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        const string ADD_FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            XDocument doc = XDocument.Load(FILENAME);
            XDocument addDoc = XDocument.Load(ADD_FILENAME);

            XElement docRoot = doc.Root;
            XElement addRoot = addDoc.Root;

            foreach (XElement child in addRoot.Elements())
            {
                string elementName = child.Name.LocalName;

                XElement docElement = docRoot.Element(elementName);

                docElement.Add(child.FirstNode);
            }


        }
    }
}

答案 1 :(得分:1)

根据jdweng的回答,这就是我想出来的。再次感谢,伙计们!

using System;
using System.Linq;
using System.Xml.Linq;

namespace WeaponInfoTemplateGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 0)
                return;

            if (!args.All(i => i.EndsWith(".meta")) && !args.All(i => i.EndsWith(".xml")))
                return;

            try
            {
                for (int i = 0; i < args.Length; i++)
                {
                    var arg = args[i];
                    Console.WriteLine("Enter a string value:");
                    var userInput = Console.ReadLine();

                    XDocument doc = XDocument.Load(arg);
                    doc.RemoveSimilarNodes(userInput, "Entry", "SlotNavigateOrder", "Item", "WeaponSlots", "Item");
                    doc.RemoveSimilarNodes(userInput, "Entry", "SlotBestOrder", "WeaponSlots", "Item");
                    doc.ClearNode("TintSpecValues");
                    doc.ClearNode("FiringPatternAliases");
                    doc.ClearNode("UpperBodyFixupExpressionData");
                    doc.ClearNode("AimingInfos");
                    doc.RemoveSimilarNodes(userInput, "Name", "Infos", "Item", "Infos", "Item");
                    doc.ClearNode("VehicleWeaponInfos");
                    doc.Save(arg + ".new.xml");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
                Console.ReadLine();
            }

            Console.WriteLine("Press [Enter] to exit...");
            Console.ReadLine();
        }
    }
}
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace WeaponInfoTemplateGenerator
{
    public static class Util
    {

        public static void RemoveSimilarNodes(this XDocument doc, string targetStringValue, string targetDescendant, params string[] path)
        {
            // Go to the last node.
            IEnumerable<XElement> currentNode = null;
            for (int i = 0; i < path.Length; i++)
            {
                string name = path[i];
                if (currentNode == null)
                {
                    currentNode = doc.Descendants(name);
                    continue;
                }

                currentNode = currentNode.Descendants(name);
            }

            // Check the target descendant, and get it's children.
            List<XElement> navOrders = currentNode.Where(x => !x.Descendants(targetDescendant).Where(y => ((string)y).Contains(targetStringValue)).Any()).ToList();

            // Remove the nodes.
            foreach (XElement node in navOrders)
            {
                node.Remove();
            }
        }

        public static void ClearNode(this XDocument doc, string descendant)
        {
            List<XElement> desc = doc.Descendants(descendant).ToList();
            desc.DescendantNodes().Remove();
        }
    }
}