• 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:
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>
You are adding conditions to your spawn in your first example that limits the changes it does.

Here, you are saying change the 2nd spawn node's maxcount:

Code:
<set xpath="/spawning/biome[@name='pine_forest']/spawn[2]/@maxcount">2</set>
or you could loosen up your filter, and remove the condition on the spawn node, and it'd apply to all spawns in the pine_forest biome:

Code:
<set xpath="/spawning/biome[@name='pine_forest']/spawn/@maxcount">2</set>
For your second example, that should work, and adjust each Mass value for each zombie. It will not add a Mass property if it doesn't exists.

 
You are adding conditions to your spawn in your first example that limits the changes it does.
Here, you are saying change the 2nd spawn node's maxcount:

Code:
<set xpath="/spawning/biome[@name='pine_forest']/spawn[2]/@maxcount">2</set>
or you could loosen up your filter, and remove the condition on the spawn node, and it'd apply to all spawns in the pine_forest biome:

Code:
<set xpath="/spawning/biome[@name='pine_forest']/spawn/@maxcount">2</set>
Yeah, figured that one out, problem is I'd like to be able to specify a different value for each spawn using only one xpath instead of 3, not apply the same value to all spawn nodes. ;)

For your second example, that should work, and adjust each Mass value for each zombie. It will not add a Mass property if it doesn't exists.
I just wanted to add another example without the index, but it's basically the same request: modify more than one variable on the same xpath instead of using a seperate xpath for each and every property of the same class.

Just wanted to know if that is even possible, and if yes how. ;p

 
Help, i'm trying to change the drop on destroy commands for a specific item, tree and I can accomplish easily insert and insert the entire code of the tree. But i'd rather do this the right way with set xpath and i do not think i can get into the right node to make my changes.

Here is original:

<block name="treeCactus01">

SNIP ************

<drop event="Harvest" name="resourceYuccaFibers" count="10" tag="oreWoodHarvest"/>

<drop event="Destroy" name="foodCropYuccaFruit" count="3" prob="1"/>

<drop event="Destroy" name="resourceYuccaFibers" count="5"/>

SNIP ***************

</block>

Here is my updated line after trying so many variations. Goal, to make the above cactus drop 20 Fibers instead of 3. Code says 5, but in my game it drops 3. ???

<set xpath="/blocks/block[@name=treeCactus01]/drop[@event=Destroy][@name=resourceYuccaFibers]/@count">20</set>

Any help would be appreciated.

Thanks

 
sbangs007 I had a similar problem, my code was

Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@event='harvest'][@name='resourceFemur][@tag='butcherHarvest']/@count">5</set>
What i found to work was this

Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@tag='butcherHarvest']/@count">5</set>
so for you i would have somthing like this

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>
 
sbangs007 I had a similar problem, my code was
Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@event='harvest'][@name='resourceFemur][@tag='butcherHarvest']/@count">5</set>
What i found to work was this

Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@tag='butcherHarvest']/@count">5</set>
so for you i would have somthing like this

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>
ok thanks, will give that a go.. appreciate the info

- - - Updated - - -

sbangs007 I had a similar problem, my code was
Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@event='harvest'][@name='resourceFemur][@tag='butcherHarvest']/@count">5</set>
What i found to work was this

Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@tag='butcherHarvest']/@count">5</set>
so for you i would have somthing like this

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>
Question, since you have it in your example, what is the purpose or definition of a "tag" with 7days?

Thanks

 
sbangs007 I had a similar problem, my code was
Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@event='harvest'][@name='resourceFemur][@tag='butcherHarvest']/@count">5</set>
What i found to work was this

Code:
<set xpath="/entity_classes/entity_class[@name='animalStag']/drop[@tag='butcherHarvest']/@count">5</set>
so for you i would have somthing like this

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>

So i used this...

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>
Didnt work. No errors, but the cactus01 just gave 3 the default. So i also tested this line, just to be sure i was in the right node.

Code:
<set xpath="/blocks/block[@name='treeCactus01']/property[@name='OnlySimpleRotations']/@value">false</set>
Since I know that syntax really well, little room for error, and that code failed too. The trees were able to use advanced rotation.

So I dont think, i'm getting the first part right or getting into the correct node, ugh, not sure.

 
In the code I was working with the tag was being used to define how the animal was being harvested, ie with hunting knife or butcherHarvest vs say a stone ax an alltoolsharvest.

I am no expert but i see Tag used to say if a recipe is learnable etc... thus i would define it as a way of setting parameters to use or get somthing.

Hope that helps maybe a more experienced coder can give us a better definition of the Tag .

 
have you tried the and?

something like this

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@event='Destroy' and @name='resourceYuccaFibers']/@count">20</set>
 
have you tried the and?
something like this

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@event='Destroy' and @name='resourceYuccaFibers']/@count">20</set>
yea, just now.. but still not working, again no error, but no change in drop.

Also, i cant even get the basic code for rotation changed, code is in an updated reply above. So if thats not working, im missing the entire node in my opinion.

 
yea, just now.. but still not working, again no error, but no change in drop.
Also, i cant even get the basic code for rotation changed, code is in an updated reply above. So if thats not working, im missing the entire node in my opinion.
Those are valid xpath. Have you checked the output of exportcurrentconfigs? Do you have a log file?

 
no, i havent.. prob my next step i figure :)

Ok, got the logs, and checked my target node. Nothing is being changed.. ugh

Code:
<block name="treeCactus01">
<property name="Class" value="Cactus" />
<property name="DisplayType" value="blockMulti" />
<property name="Material" value="Mcactus" />
<property name="Shape" value="DistantDeco" />
<property name="Model" value="Entities/Trees/Saguaro_Cactus_20Prefab" />
<property name="ModelOffset" value="0,-0.1,0" />
<property name="MultiBlockDim" value="1,6,1" />
<property name="IsTerrainDecoration" value="true" />
<property name="IsDistantDecoration" value="true" />
<property name="ImposterDontBlock" value="true" />
<property name="BigDecorationRadius" value="2" />
<property name="OnlySimpleRotations" value="true" />
<property name="Tag" value="TreeTrunk" />
<property name="Damage" value="3" />
<property name="IsPlant" value="true" />
<property name="CanPlayersSpawnOn" value="false" />
<drop event="Harvest" name="resourceYuccaFibers" count="10" tag="oreWoodHarvest" />
<drop event="Destroy" name="foodCropYuccaFruit" count="3" prob="1" />
<drop event="Destroy" name="resourceYuccaFibers" count="5" />
<property name="FilterTags" value="foutdoor,fcactus,fshrubbery" />
<property name="SortOrder1" value="a0e0" />
<property name="ActivationDistance" value="10" />
</block>
 
Ok, got the logs, and checked my target node. Nothing is being changed.. ugh

Code:
<block name="treeCactus01">
<property name="Class" value="Cactus" />
<property name="DisplayType" value="blockMulti" />
<property name="Material" value="Mcactus" />
<property name="Shape" value="DistantDeco" />
<property name="Model" value="Entities/Trees/Saguaro_Cactus_20Prefab" />
<property name="ModelOffset" value="0,-0.1,0" />
<property name="MultiBlockDim" value="1,6,1" />
<property name="IsTerrainDecoration" value="true" />
<property name="IsDistantDecoration" value="true" />
<property name="ImposterDontBlock" value="true" />
<property name="BigDecorationRadius" value="2" />
<property name="OnlySimpleRotations" value="true" />
<property name="Tag" value="TreeTrunk" />
<property name="Damage" value="3" />
<property name="IsPlant" value="true" />
<property name="CanPlayersSpawnOn" value="false" />
<drop event="Harvest" name="resourceYuccaFibers" count="10" tag="oreWoodHarvest" />
<drop event="Destroy" name="foodCropYuccaFruit" count="3" prob="1" />
<drop event="Destroy" name="resourceYuccaFibers" count="5" />
<property name="FilterTags" value="foutdoor,fcactus,fshrubbery" />
<property name="SortOrder1" value="a0e0" />
<property name="ActivationDistance" value="10" />
</block>
You got that snippet from your main 7 Days To Die Config folder, or from the Save Game folder?

 
2019-04-11 09_29_05-Window.jpg

That was the location

I test it on my single player client machine, when the mod works, i then dump it over to my server machine.

- - - Updated - - -

2019-04-11 09_29_05-Window.jpg

That was the location

I test it on my single player client machine, when the mod works, i then dump it over to my server machine.

I decided to test another xml file for a mod of a sport bike i made, and that mod is present. So this is the right folder.

 
View attachment 28157
That was the location

I test it on my single player client machine, when the mod works, i then dump it over to my server machine.

- - - Updated - - -

View attachment 28157

That was the location

I test it on my single player client machine, when the mod works, i then dump it over to my server machine.

I decided to test another xml file for a mod of a sport bike i made, and that mod is present. So this is the right folder.
Anything in your output_log.txt about the modlet not loading?

 
Anything in your output_log.txt about the modlet not loading?
Yep the mod loaded with no issues.

Sbangs007 INPROGRESS

2019-04-11T09:28:09 5.923 INF [MODS] Loaded Mod: Cactus Drop (1.0)

2019-04-11T09:28:09 5.923 INF [MODS] Initializing mod code

2019-04-11T09:28:09 5.923 INF [MODS] Loading done

So weird, but a challenge..

 
Yep the mod loaded with no issues.
Sbangs007 INPROGRESS

2019-04-11T09:28:09 5.923 INF [MODS] Loaded Mod: Cactus Drop (1.0)

2019-04-11T09:28:09 5.923 INF [MODS] Initializing mod code

2019-04-11T09:28:09 5.923 INF [MODS] Loading done

So weird, but a challenge..
introduce an error in your xpath so it'll fail.. change the block name to something that isn't available, re-try and see if it detects the error.

If it does not detect the error, it does not see your file at all. We'd want to take a look at your folder structure Mods/<ModName>/Config/blocks.xml or the full file of your changes.

 
introduce an error in your xpath so it'll fail.. change the block name to something that isn't available, re-try and see if it detects the error.
If it does not detect the error, it does not see your file at all. We'd want to take a look at your folder structure Mods/<ModName>/Config/blocks.xml or the full file of your changes.
Interesting.. got two YELLOW errors and i may have not seen these before, as they were not RED.

2019-04-11 13_32_16-7 Days To Die.jpg

2019-04-11 13_32_26-7 Days To Die.jpg

Here was my code, i also removed an @ in line 2 in hopes of generating a typical RED syntax error, but it did not. Glad i scrolled up to check for other errors.

Code:
<ModFeatherFall>

<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFruit']/count">20</set>
<set xpath="/blocks/block[@name='treeCactus01']/property[@name='OnlySimpleRotations']/@value">false</set>
<set xpath="/blocks/block[@name='treeCactus01']/drop[@event='Destroy' and @name='resourceYuccaFruit']/@count">20</set>

</ModFeatherFall>
hmmmm...

- - - Updated - - -

introduce an error in your xpath so it'll fail.. change the block name to something that isn't available, re-try and see if it detects the error.
If it does not detect the error, it does not see your file at all. We'd want to take a look at your folder structure Mods/<ModName>/Config/blocks.xml or the full file of your changes.
Shoot screenshot to small to read, here is the error

WRN XML patch for blocks.xml did not apply for line 2 and 4 of the above code.

That was it

 
So i used this...
Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>
Didnt work. No errors, but the cactus01 just gave 3 the default. So i also tested this line, just to be sure i was in the right node.

Code:
<set xpath="/blocks/block[@name='treeCactus01']/property[@name='OnlySimpleRotations']/@value">false</set>
Since I know that syntax really well, little room for error, and that code failed too. The trees were able to use advanced rotation.

So I dont think, i'm getting the first part right or getting into the correct node, ugh, not sure.
your orginal suggestion WORKED!!

Code:
<set xpath="/blocks/block[@name='treeCactus01']/drop[@name='resourceYuccaFibers']/@count">20</set>
I was never checking the fibers as i was checking fruit. Also a huge red flag that kept me from troublshooting, was the simple rotation, that even editing the orginal XML file for the game, never worked, so it was a bad red hearing to use for testing.

I cant believe this.. thank you so much for your time with this issue, but wanted you to know, the your first code was the correct one that worked all this time. Ugh..

 
Back
Top