• If you have a mod, tool or prefab, please use the Resources section. Click Mods at the top of the forums.

XPath Modding Explanation Thread

This is a large amount of information in these posts. I'll be working on a full, properly formed tutorial as we get access to A17 and we can really make the xpath system shine. I've listed some examples here, and we'll be posting a ton more xpath samples over the coming weeks, as we port the SDX modlets over to use the native hooks.

By all means, begin posting your comments, questions, or requests for clarity.

Since we now know that xpath support will be built-into the vanilla base game, and discussions earlier were getting a bit confusing, I've decided to make a new thread to try to demystify xpath and what it'll mean for mods and modders going forward in A17. The information in this thread has been pieced together from forum and discord discussions. They may not be 100% accurate, but I will update this thread when we know the full implementation.

XPath is a way of adding, changing, or removing XML lines and nodes, without directly editing the XML files. It allows you to apply patches to the XML files without manually editing the vanilla XML files.

SDX has had partial support for this since its initial release, and a lot of the SDX Modlets are already written this way. We will be using some of the SDX's xpath as examples in this thread, but SDX is not required to do this in A17 and onwards.

I believe in using examples to explain concept, so in the next few posts, you'll see a mixture of explanation, along with sample xpath code.

The following Mod structure is expected for A17 and beyond:

Code:
Mods/
   <ModName>/
       Config/
       UIAtlases/ItemIconAtlas/
       ModInfo.xml

   <ModName2>/
       Config/
       ModInfo.xml
You will be able to have multiple mods loaded, and loading will occur as long as the ModInfo.xml exists. This is unchanged from what we've been doing doing with other alphas, with the exception of the Config folder.

This Config folder will support loading XML files, written using xpath, in the following folder structure:

Code:
Config/entityclasses.xml
Config/gamestages.xml
Config/items.xml
The files in the Config folder will not be a full copy of the vanilla file with your changes. Rather, it'll contain the changes you want done to the vanilla files. The files under the Config must match the vanilla file name. You cannot create an entityclasses2.xml file, and expect it to work. Any changes in the entityclasses.xml will have to be done in the same file. However, each mod can have its own entityclasses.xml.

During the game's initialization, it will perform the xpath merge in-memory only; no files will be actually be modified. This would allow us to remove mods we no longer want, without re-validating against steam, or previous copies of the xml. That's a big one. No more half merging of a mod, and not having it work, then trying to pull it back out.

What this means for us is that we'll be able to make a variety of smaller mods, which I've been calling modlets, which can add, remove and change smaller pieces of the game. They can be used together, or they could be added to an overhaul mod, in order to style your game play easier.

These modlets would also exists outside of the Data/Config folder, so if you have made direct XML changes in your Alpha 17.1 Data/Config files, and Steam updated the game to 17.2, you would have lost your changes, or would have to re-merge them in. We've all been there before. But if they existed as modlets, under the Mods folder, they would be safe. And as long as your xpath is still valid to the new XML, it should load up with no additional work on your part.

If we could use xyth's JunkItems modlet, which adds random, scrappable junk items to loot containers, and add them to Valmod Overhaul. Likewise, if Valmod Overhaul did not have the No Ammo modlet (which gives you the ability to unload a gun and get its bullets back without disassembling it), you could drop the NoAmmo modlet into your Mods folder. Headshots only? Want to increase stack sizes? Same deal.

With a properly constructed modlet, we'll be able to piece together new play styles for people to enjoy and share. A modder working on a large overhaul won't have to duplicate work. If they wanted to include the No Ammo mod, they wouldn't have to code it themselves, letting them focus on the bits that make their mod really unique.

Let's get started on your journey...

 
Last edited by a moderator:
I am having an issue with xpath and Blocks is there a way to add in a property to an existing block or do i need to remove the block some how and append in a replacement one with the changes?
is this used to remove the block, if so could someone explain how.

i Thank you for any help you may provide.
iam very "noobish", but better quick reply then nothing. why dont u use set or append to change that block?!

 
iam very "noobish", but better quick reply then nothing. why dont u use set or append to change that block?!
sorry should elaborate on what i need to do i need to add in a property line that is not in the block.

<append xpath="/blocks/block[@name=NAMEOFITEMADDINGTO]/property[@name=NAMEOFPROPERTY' and @value='PROPERTYVALUE]/@value"></append>
i have tried it this way but it don't seem to work.

 
Code:
<append xpath="/blocks/block[@name='NAMEOFITEMADDINGTO']
<property name="NAMEOFPROPERTY" value="PROPERTYVALUE"/>
</append>
 
Last edited by a moderator:
Code:
<append xpath="/blocks/block[@name='NAMEOFITEMADDINGTO']
<property name="NAMEOFPROPERTY" value="PROPERTYVALUE"/>
</append>
Sure This is the way it should be i get errors

Code:
<append xpath="/blocks/block[@name='NAMEOFITEMADDINGTO']">
     <property name="NAMEOFPROPERTY" value="PROPERTYVALUE"/>
   </append>
 
We would need to see just what you are trying to do to be of any help, or at least I would.
Got it working.

Code:
   <append xpath="/blocks/block[@name='NAMEOFBLOCKADDINGTO']">
         <property name="NAMEOFPROPERTY" value="PROPERTYVALUE"/>
   </append>
Thank You For All The Help :)

 
Heya, i'm having a bit of trouble, this line of code is supposed to replace the original entry in another mod.

Code:
<set xpath="/items/item[@name='Luger']/property[@class='Action0']/property[@name='Magazine_items'][@value='9x19mm Bullet']/@value">ammo9mmBullet,ammo9mmBulletSteel,9x19mm Bullet,9x19mm JHP Bullet,9x19mm FMJ Bullet,9x19mm Bullet Steel,9x19mm JHP Bullet Steel,9x19mm FMJ Bullet Steel,ammo9mmBullet,ammo9mmBulletSteel</set>
for some reason, it simply refuses to make the change, am i missing something?

 
Heya, i'm having a bit of trouble, this line of code is supposed to replace the original entry in another mod.

Code:
<set xpath="/items/item[@name='Luger']/property[@class='Action0']/property[@name='Magazine_items'][@value='9x19mm Bullet']/@value">ammo9mmBullet,ammo9mmBulletSteel,9x19mm Bullet,9x19mm JHP Bullet,9x19mm FMJ Bullet,9x19mm Bullet Steel,9x19mm JHP Bullet Steel,9x19mm FMJ Bullet Steel,ammo9mmBullet,ammo9mmBulletSteel</set>
for some reason, it simply refuses to make the change, am i missing something?
is this xpath running from a modlet after the original one, or before it? Do you have the output_log.txt? If it does not apply, it should be displayed in the logs.

 
hmm, it is loading after, but i haven't thought to check the log yet, i guess what i'm asking is if my syntax is correct?

well, the log shows no evidence of rejection.

Code:
2019-03-22T21:06:17 12.032 INF [MODS] Start loading
2019-03-22T21:06:17 12.034 INF [MODS] Trying to load from Firearms
2019-03-22T21:06:17 12.072 INF [MODS] Loaded Mod: Mayics Custom Firearms (1.2)
2019-03-22T21:06:17 12.072 INF [MODS] Trying to load from JRB_ZombieLootDrop_15
2019-03-22T21:06:17 12.077 INF [MODS] Loaded Mod: JRB_ZombieLootDrop_15 (3.0)
2019-03-22T21:06:17 12.077 INF [MODS] Trying to load from Melee
2019-03-22T21:06:17 12.078 INF [MODS] Loaded Mod: Melee (1.0)
2019-03-22T21:06:17 12.078 INF [MODS] Trying to load from S420_SimpleUI-BiggerBackpack120
2019-03-22T21:06:17 12.082 INF [MODS] Loaded Mod: S420_SimpleUI-BiggerBackpack120 (1.0)
2019-03-22T21:06:17 12.082 INF [MODS] Trying to load from S420_SimpleUI-Compass
2019-03-22T21:06:17 12.087 INF [MODS] Loaded Mod: S420_SimpleUI-Compass (1.0)
2019-03-22T21:06:17 12.087 INF [MODS] Trying to load from S420_SimpleUI-CraftingQueue
2019-03-22T21:06:17 12.091 INF [MODS] Loaded Mod: S420_SimpleUI-CraftingQueue (1.0)
2019-03-22T21:06:17 12.091 INF [MODS] Trying to load from S420_SimpleUI-ForgeInput
2019-03-22T21:06:17 12.092 INF [MODS] Loaded Mod: S420_SimpleUI-ForgeInput (1.0)
2019-03-22T21:06:17 12.092 INF [MODS] Trying to load from S420_SimpleUI-LeftHUD
2019-03-22T21:06:17 12.094 INF [MODS] Loaded Mod: S420_SimpleUI-LeftHUD (1.0)
2019-03-22T21:06:17 12.094 INF [MODS] Trying to load from SovietWeaponPack
2019-03-22T21:06:17 12.095 INF [MODS] Loaded Mod: SovietPack (1.2.1)
2019-03-22T21:06:17 12.096 INF [MODS] Trying to load from XXAdvancedAmmoCrafting
2019-03-22T21:06:17 12.102 INF [MODS] Loaded Mod: Olfurinars Advanced Ammo Crafting (1.0)
2019-03-22T21:06:17 12.102 INF [MODS] Initializing mod code
2019-03-22T21:06:17 12.103 INF [MODS] Loading done
 
Last edited by a moderator:
hmm, it is loading after, but i haven't thought to check the log yet, i guess what i'm asking is if my syntax is correct?
well, the log shows no evidence of rejection.

Code:
2019-03-22T21:06:17 12.032 INF [MODS] Start loading
2019-03-22T21:06:17 12.034 INF [MODS] Trying to load from Firearms
2019-03-22T21:06:17 12.072 INF [MODS] Loaded Mod: Mayics Custom Firearms (1.2)
2019-03-22T21:06:17 12.072 INF [MODS] Trying to load from JRB_ZombieLootDrop_15
2019-03-22T21:06:17 12.077 INF [MODS] Loaded Mod: JRB_ZombieLootDrop_15 (3.0)
2019-03-22T21:06:17 12.077 INF [MODS] Trying to load from Melee
2019-03-22T21:06:17 12.078 INF [MODS] Loaded Mod: Melee (1.0)
2019-03-22T21:06:17 12.078 INF [MODS] Trying to load from S420_SimpleUI-BiggerBackpack120
2019-03-22T21:06:17 12.082 INF [MODS] Loaded Mod: S420_SimpleUI-BiggerBackpack120 (1.0)
2019-03-22T21:06:17 12.082 INF [MODS] Trying to load from S420_SimpleUI-Compass
2019-03-22T21:06:17 12.087 INF [MODS] Loaded Mod: S420_SimpleUI-Compass (1.0)
2019-03-22T21:06:17 12.087 INF [MODS] Trying to load from S420_SimpleUI-CraftingQueue
2019-03-22T21:06:17 12.091 INF [MODS] Loaded Mod: S420_SimpleUI-CraftingQueue (1.0)
2019-03-22T21:06:17 12.091 INF [MODS] Trying to load from S420_SimpleUI-ForgeInput
2019-03-22T21:06:17 12.092 INF [MODS] Loaded Mod: S420_SimpleUI-ForgeInput (1.0)
2019-03-22T21:06:17 12.092 INF [MODS] Trying to load from S420_SimpleUI-LeftHUD
2019-03-22T21:06:17 12.094 INF [MODS] Loaded Mod: S420_SimpleUI-LeftHUD (1.0)
2019-03-22T21:06:17 12.094 INF [MODS] Trying to load from SovietWeaponPack
2019-03-22T21:06:17 12.095 INF [MODS] Loaded Mod: SovietPack (1.2.1)
2019-03-22T21:06:17 12.096 INF [MODS] Trying to load from XXAdvancedAmmoCrafting
2019-03-22T21:06:17 12.102 INF [MODS] Loaded Mod: Olfurinars Advanced Ammo Crafting (1.0)
2019-03-22T21:06:17 12.102 INF [MODS] Initializing mod code
2019-03-22T21:06:17 12.103 INF [MODS] Loading done
Nothing stands out at a glance, but I don't see the structure of the item you are changing. Any WARN errors after the log of it parsing?

If you load into a game, do an "exportcurrentconfigs" in the console, is your changes applied?

 
The original code,

Code:
<item name="Luger">
<snipped>
<property class="Action0">
	<property name="Magazine_items" value="9x19mm Bullet"/>
<snipped>
</item>
What i need it to be,

Code:
<item name="Luger">
<snipped>
<property class="Action0">
	<property name="Magazine_items" value="ammo9mmBullet,ammo9mmBulletSteel,9x19mm Bullet,9x19mm JHP Bullet,9x19mm FMJ Bullet,9x19mm Bullet Steel,9x19mm JHP Bullet Steel,9x19mm FMJ Bullet Steel"/>
<snipped>
</item>
I'm terribly sorry, i keep forgetting... we have an ammo type limit of 8 types per weapon, i was trying to shove in 10.

:shame:

 
The original code,
Code:
<item name="Luger">
<snipped>
<property class="Action0">
	<property name="Magazine_items" value="9x19mm Bullet"/>
<snipped>
</item>
What i need it to be,

Code:
<item name="Luger">
<snipped>
<property class="Action0">
	<property name="Magazine_items" value="ammo9mmBullet,ammo9mmBulletSteel,9x19mm Bullet,9x19mm JHP Bullet,9x19mm FMJ Bullet,9x19mm Bullet Steel,9x19mm JHP Bullet Steel,9x19mm FMJ Bullet Steel"/>
<snipped>
</item>
I'm terribly sorry, i keep forgetting... we have an ammo type limit of 8 types per weapon, i was trying to shove in 10.

:shame:
So all good... or no? :)

 
if i wanted to swap out the entire section of the property name="RandomTintColor of the cars, would i need to do each tint color individually or is there a way to change it as a group?

 
Hey everyone, working on some mods and I can't seem to get this to work.

code:

<remove xpath="/lootcontainers/lootgroup[@name=weaponsHuntingRifle+ammo]/item[@name'ammo762mmBulletFMJ']"/>

I want to remove the ammo from the loot group so i can insert other ammo that the hunting rifle now fires.

 
Hey everyone, working on some mods and I can't seem to get this to work.
code:

<remove xpath="/lootcontainers/lootgroup[@name=weaponsHuntingRifle+ammo]/item[@name'ammo762mmBulletFMJ']"/>

I want to remove the ammo from the loot group so i can insert other ammo that the hunting rifle now fires.
Sorry for the delay. Your xpath is nearly correct. You forgot a = between @name='ammo762mmBulletFMJ']

- - - Updated - - -

if i wanted to swap out the entire section of the property name="RandomTintColor of the cars, would i need to do each tint color individually or is there a way to change it as a group?
I'm sorry, I didn't see your message earlier.

you can do things like this, which will change all the RandomTintColor1 value in the entire file. You can just omit the block[@name=''] condition.

Code:
<set xpath="/blocks/block/property[@name='RandomTintColor1']/@value">0,200,0</set>
 
Hi, I've been toying around with xpath since yesterday and I couldn't figure out how to set more than one variable (modify an existing variable) with the same set xpath command, I basically just copy pasted the almost same thing 3 times. I was wondering if there was a way to simplify this for future use, thanks!

Here's an example where I had to use an index since I don't think I can distinguish the spawner from one another any other way (feel free to correct me on this).

Here's the original xml code

Code:
	<biome name="pine_forest">
	<spawn maxcount="2" respawndelay="4" time="Any" entitygroup="ZombiesAll" />
	<spawn maxcount="1" respawndelay="7" time="Any" entitygroup="EnemyAnimalsForest" spawnDeadChance="0" />
	<spawn maxcount="1" respawndelay="7" time="Any" entitygroup="FriendlyAnimalsForest" spawnDeadChance="0" />
</biome>
And here's the xpath to change the max count of each line

Code:
<set xpath="/spawning/biome[@name='pine_forest']/spawn[1]/@maxcount">5</set>
<set xpath="/spawning/biome[@name='pine_forest']/spawn[2]/@maxcount">2</set>
<set xpath="/spawning/biome[@name='pine_forest']/spawn[3]/@maxcount">3</set>
Can this be done in just one xpath? Kinda like this

Code:
<set xpath="/spawning/biome[@name='pine_forest']
spawn[1]/@maxcount" 5
spawn[2]/@maxcount" 2
spawn[3]/@maxcount" 3
</set>
Another example where I'd like to modify a bunch of variables for all zombies, here's the original in entityclasses.xml (just random variables for testing)

Code:
<entity_class name="zombieTemplateMale">
<!-- other variables -->
<property name="Mass" value="170"/>
<property name="Weight" value="70"/>
<property name="MaxViewAngle" value="180"/>
<property name="SightRange" value="30"/> 
<!-- other variables -->
</entity_class>
And here's the code to change just one of those variables, but I would basically have to copy paste almost the same set command for each variable I'd like to change. Again if all 4 could be done with just one command I would appreciate a hint or two. ;p

Code:
<set xpath="/entity_classes/entity_class[starts-with(@name, 'zombie')]/property[@name='Mass']/@value">420</set>
 
Back
Top