• 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:
@sphereii Bro this is driving me crazy lol I am seeing in the posts some using <config> and others using <configs> which should we be using lol sorry want to make sure it's all in line.

Also I am not sure how to handle this and hoping you can tell me the best way to do this. I am adding about 95 new entities and and not really sure with the entitiesgroup.xml how should I take care of this? Here is what I mean, adding the new entities to each group easy.

The part I am not sure how to deal with this is alllllll the Sleeper generated and Horde generated codes at the bottom that HUGE LONG list. I mean I know I have to do it if I want the new entities in different game stages to appear properly. Would we really have to remove each and every single one of those or is there a faster way for that?
The top level that you are seeing <configs> and <config> are what's called a root node for an XML file. It can nearly be anything (except for leading with numbers...). I try to use <configs> because that's brought over from SDX, but as long as your opening node and closing tag matches, it doesn't really matter.

Code:
<FastBurst>
  <!-- all your xml changes -->
</FastBurst>
Can you be more specific about what you are trying to do? Are you trying to add 95 new entities to a single group, or scattered about? If you can give me an example of what you'd like to see, I'd be able to help more.

 
The top level that you are seeing <configs> and <config> are what's called a root node for an XML file. It can nearly be anything (except for leading with numbers...). I try to use <configs> because that's brought over from SDX, but as long as your opening node and closing tag matches, it doesn't really matter.

Code:
<FastBurst>
  <!-- all your xml changes -->
</FastBurst>
Can you be more specific about what you are trying to do? Are you trying to add 95 new entities to a single group, or scattered about? If you can give me an example of what you'd like to see, I'd be able to help more.
I have 95 new entities/Zs that I have created. I know I can amend each of the groups - Like ZombiesAll etc etc. I did all that with A16 then I used that Google Spreadsheet to add them in for the generated like bloodmoon and hordes and sleepers. And as we all know thats a HUGE chunk of data especially if you're adding in 95 more Zs to the game. - again did all that with A16 and worked BEAUTIFULLY with no issues, Bloodmoon nights were amazing, seeing upwards of 60 different Zs coming at you and different types of waves.

Now with A17, I wanted to create that same experience using the Mod System. But how to do we change the Generated Code from the spreadsheet? Meaning I have the generated code that's easy to do. What I want to know for those random generated sections on the vanilla file, is there an easy way to remove that entire chunk so I can just amend and insert the new code.

What I fear is would have to MANUALLY add each and remove them like <entitygroup name="wanderingHordeStageGS1"> and <entitygroup name="wanderingHordeStageGS2"> and so on and so on. That would suck major monkey #$%^ if that's the case because there has to be literally over 1000+ easy with all those generated sections. On the entitygroups.xml line 351 is where all that starts and ends all the way to the bottom line 1875

I don't know if there is a magic solution for this to remove that entire data so that we can just add the new data of the new generated parts.

 
I have 95 new entities/Zs that I have created. I know I can amend each of the groups - Like ZombiesAll etc etc. I did all that with A16 then I used that Google Spreadsheet to add them in for the generated like bloodmoon and hordes and sleepers. And as we all know thats a HUGE chunk of data especially if you're adding in 95 more Zs to the game. - again did all that with A16 and worked BEAUTIFULLY with no issues, Bloodmoon nights were amazing, seeing upwards of 60 different Zs coming at you and different types of waves.
Now with A17, I wanted to create that same experience using the Mod System. But how to do we change the Generated Code from the spreadsheet? Meaning I have the generated code that's easy to do. What I want to know for those random generated sections on the vanilla file, is there an easy way to remove that entire chunk so I can just amend and insert the new code.

What I fear is would have to MANUALLY add each and remove them like <entitygroup name="wanderingHordeStageGS1"> and <entitygroup name="wanderingHordeStageGS2"> and so on and so on. That would suck major monkey #$%^ if that's the case because there has to be literally over 1000+ easy with all those generated sections. On the entitygroups.xml line 351 is where all that starts and ends all the way to the bottom line 1875

I don't know if there is a magic solution for this to remove that entire data so that we can just add the new data of the new generated parts.
You could probably do a <remove xpath="/entitygroups/entitygroup" />, and re-append the entire file. I'm not sure what the format of your game stage is in.

 
You could probably do a <remove xpath="/entitygroups/entitygroup" />, and re-append the entire file. I'm not sure what the format of your game stage is in.
So using that, that basically removes the entire file? and I would just use append and just basically add the entire modded file back in basically?

If so, that's even better at least for me that is lol

 
So using that, that basically removes the entire file? and I would just use append and just basically add the entire modded file back in basically?If so, that's even better at least for me that is lol
It's not the most elegant way, but if you are already generating replacement nodes, it's certainly a way to do it. It'd probably wouldn't be compatible with many other modlets, unless they loaded after your nuke.

 
It's not the most elegant way, but if you are already generating replacement nodes, it's certainly a way to do it. It'd probably wouldn't be compatible with many other modlets, unless they loaded after your nuke.
I am not worried about that, my mod is for my personal server. Haven't thought about actually releasing it to the public.

Below is something I wanted to make sure I did correctly. So with b208 the TFP took out the ability to upgrade to stainless steel - well I am adding it back in. I wanted to make sure for the SteelPolish I added in correctly or can I slim the code down a bit? do I need to list all of those or is there a way to add to the end of that list?

items.xml

Code:
<set xpath="/items/item/property[@class='Action1']/property[@name='Allowed_upgrade_items'][@value='resourceWood,resourceClayLump,resourceSnowBall,resourceScrapIron,resourceForgedIron,resourceForgedSteel,resourceConcreteMix,resourceCobblestones,resourceYuccaFibers,resourceNail']/@value">,resourceSteelPolish</set>

<remove xpath="/items/item/[@name='resourceSteelPolish']/property[@name='CreativeMode']" />
blocks.xml

Code:
<configs>
<append xpath="/blocks/block[@name='steelMaster']">
	<property class="UpgradeBlock">
		<property name="ToBlock" value="stainlessSteelMaster"/>
		<property name="Item" value="resourceSteelPolish"/>
		<property name="ItemCount" value="10"/>
		<property name="UpgradeHitCount" value="4"/>
	</property>
</append>
</configs>
Keep in mind this is my first attempt at using the xpath way of modding. I believe I did it correctly.

 
I am not worried about that, my mod is for my personal server. Haven't thought about actually releasing it to the public.

Below is something I wanted to make sure I did correctly. So with b208 the TFP took out the ability to upgrade to stainless steel - well I am adding it back in. I wanted to make sure for the SteelPolish I added in correctly or can I slim the code down a bit? do I need to list all of those or is there a way to add to the end of that list?

items.xml

Code:
<set xpath="/items/item/property[@class='Action1']/property[@name='Allowed_upgrade_items'][@value='resourceWood,resourceClayLump,resourceSnowBall,resourceScrapIron,resourceForgedIron,resourceForgedSteel,resourceConcreteMix,resourceCobblestones,resourceYuccaFibers,resourceNail']/@value">,resourceSteelPolish</set>

<remove xpath="/items/item/[@name='resourceSteelPolish']/property[@name='CreativeMode']" />
blocks.xml

Code:
<configs>
<append xpath="/blocks/block[@name='steelMaster']">
	<property class="UpgradeBlock">
		<property name="ToBlock" value="stainlessSteelMaster"/>
		<property name="Item" value="resourceSteelPolish"/>
		<property name="ItemCount" value="10"/>
		<property name="UpgradeHitCount" value="4"/>
	</property>
</append>
</configs>
Keep in mind this is my first attempt at using the xpath way of modding. I believe I did it correctly.
Your set could be replaced by this:

Code:
<append xpath="/items/item/property[@class='Action1']/property[@name='Allowed_upgrade_items']/@value">,resourceSteelPolish</append>
 
Your set could be replaced by this:

Code:
<append xpath="/items/item/property[@class='Action1']/property[@name='Allowed_upgrade_items']/@value">,resourceSteelPolish</append>
The only problem is if I used that, there is one item "meleeToolHoeIron" that, it would also attach that change to. I think it would be kind of strange seeing someone upgrading Steel with a Garden Hoe LOL, maybe I am wrong :p

The other tools would be fine because they all have exactly what I put in as far as upgrading goes, the hammer, nailgun, wrench and stoneaxe.

 
The only problem is if I used that, there is one item "meleeToolHoeIron" that, it would also attach that change to. I think it would be kind of strange seeing someone upgrading Steel with a Garden Hoe LOL, maybe I am wrong :p
The other tools would be fine because they all have exactly what I put in as far as upgrading goes, the hammer, nailgun, wrench and stoneaxe.
if you wanted to explicitly exclude the meleeToolHoeIron, you could add a condition.

Code:
/items/item[@name != 'meleeToolHoeIron']/property[@class='Action1']/property[@name='Allowed_upgrade_items']/@value
 
Awwwww snap, ok ok I see your style lol loving it!

I was getting an error with this part though

Code:
<remove xpath="/items/item/[@name='resourceSteelPolish']/property[@name='CreativeMode']" />
Does that not remove the property with that name on the item? or did I screw that up somehow.

 
Awwwww snap, ok ok I see your style lol loving it!
I was getting an error with this part though

Code:
<remove xpath="/items/item/[@name='resourceSteelPolish']/property[@name='CreativeMode']" />
Does that not remove the property with that name on the item? or did I screw that up somehow.
Try removing the slash between item and [@name

xpath="/items/item[@name='....

 
Awwwww snap, ok ok I see your style lol loving it!
I was getting an error with this part though

Code:
<remove xpath="/items/item/[@name='resourceSteelPolish']/property[@name='CreativeMode']" />
Does that not remove the property with that name on the item? or did I screw that up somehow.
Took me awhile to spot, but you have an extra / after item, it should be

Code:
<remove xpath="/items/item[@name='resourceSteelPolish']/property[@name='CreativeMode']" />
You could also just change the value of CreativeMode like this instead of removing it

Code:
<set xpath="/items/item[@name='resourceSteelPolish']/property[@name='CreativeMode']/@value">Player</set>
 
So I tried adding in an item using the xpath and it throws an error and doesn't parse the items.xml file at line 16, expects item but doesn't find it. Am I just derping the code or can I not extend an item referenced in the original items.xml using xpath?

The line referenced in the error is the first </property> after <property class="Action0">.

Code:
<configs>
<!-- LAZY COPY/PASTE TEMPLATES -->
<!-- <property name="" value=""/> -->
<append xpath="/items">

	<!-- Van Helsing Crossbow -->
	<item name="gunCrossbowVanHelsing">
		<property name="Extends" value="gunCrossbow"/>
			<property name="CustomIcon" value="gunCrossbow"/><property name="CustomIconTint" value="ffff66"/>
			<property name="EconomicValue" value="1000"/>
			<property name="RepairTools" value="resourceRepairKit"/>
			<property class="Action0"/>
				<property name="Class" value="Ranged"/>
				<property name="Delay" value="0.4"/>
				<property name="Magazine_items" value="ammoCrossbowBoltStone,ammoCrossbowBoltIron, ammoCrossbowBoltSteelAP"/>
			</property>
			<effect_group name="Base Effects">
				<passive_effect name="MagazineSize" operation="base_set" value="20"/>
				<passive_effect name="EntityDamage" operation="perc_add" value=".59"/>
				<passive_effect name="SpreadDegreesVertical" operation="base_set" value="1.62"/>
				<passive_effect name="SpreadDegreesHorizontal" operation="base_set" value="1.62"/>
				<passive_effect name="SpreadMultiplierAiming" operation="base_set" value=".10"/>
				<passive_effect name="SpreadMultiplierCrouching" operation="base_set" value=".8"/>
				<passive_effect name="SpreadMultiplierWalking" operation="base_set" value="1.5"/>
				<passive_effect name="SpreadMultiplierRunning" operation="base_set" value="2.2"/>
			</effect_group>
	</item>
</append>
</configs>
Edit: this is just me trying to get proof of concept, plan on adding more stuff but wanna see it in game before I go full on coding in the perk requirements etc

 
Last edited by a moderator:
Interesting. Glad it worked. I don't think what you pasted would have been your final line though. It's probably something like:

Code:
<set xpath="/worldgeneration/biomes/biome/subbiome/layers/layer/resource[@blockname='terrOreGravelPlusIron']/@blockname">terrOreIron</set>
<Setattribute> can add a new attribute that does not exist. Maybe it updates the value if its found to exist. But your starting tag of <setattribute> wasn't matching your ending tag of </set>
Actually it worked as I typed it, I did fix the </set> to </setattribute> as that was a typo.

Is there a way to see how the game changes the files? A sort of dump for the data files it has after merging all changes? That way I can see just how it changes the line.

 
Actually it worked as I typed it, I did fix the </set> to </setattribute> as that was a typo.
Is there a way to see how the game changes the files? A sort of dump for the data files it has after merging all changes? That way I can see just how it changes the line.
Once in game, type in the console: exportcurrentconfigs

It'll save them to your saved game folder under %APPDATA%. Delete the folder, if you want to re-run the same command in the same world.

- - - Updated - - -

So I tried adding in an item using the xpath and it throws an error and doesn't parse the items.xml file at line 16, expects item but doesn't find it. Am I just derping the code or can I not extend an item referenced in the original items.xml using xpath?The line referenced in the error is the first </property> after <property class="Action0">.

Code:
<configs>
<!-- LAZY COPY/PASTE TEMPLATES -->
<!-- <property name="" value=""/> -->
<append xpath="/items">

	<!-- Van Helsing Crossbow -->
	<item name="gunCrossbowVanHelsing">
		<property name="Extends" value="gunCrossbow"/>
			<property name="CustomIcon" value="gunCrossbow"/><property name="CustomIconTint" value="ffff66"/>
			<property name="EconomicValue" value="1000"/>
			<property name="RepairTools" value="resourceRepairKit"/>
			<property class="Action0"/>
				<property name="Class" value="Ranged"/>
				<property name="Delay" value="0.4"/>
				<property name="Magazine_items" value="ammoCrossbowBoltStone,ammoCrossbowBoltIron, ammoCrossbowBoltSteelAP"/>
			</property>
			<effect_group name="Base Effects">
				<passive_effect name="MagazineSize" operation="base_set" value="20"/>
				<passive_effect name="EntityDamage" operation="perc_add" value=".59"/>
				<passive_effect name="SpreadDegreesVertical" operation="base_set" value="1.62"/>
				<passive_effect name="SpreadDegreesHorizontal" operation="base_set" value="1.62"/>
				<passive_effect name="SpreadMultiplierAiming" operation="base_set" value=".10"/>
				<passive_effect name="SpreadMultiplierCrouching" operation="base_set" value=".8"/>
				<passive_effect name="SpreadMultiplierWalking" operation="base_set" value="1.5"/>
				<passive_effect name="SpreadMultiplierRunning" operation="base_set" value="2.2"/>
			</effect_group>
	</item>
</append>
</configs>
Edit: this is just me trying to get proof of concept, plan on adding more stuff but wanna see it in game before I go full on coding in the perk requirements etc
Maybe the order is getting confused.

change your append to insertAfter

Code:
<insertAfter xpath="/items/item[@name='gunCrossbow']" >
 <!-- your stuff -->
</insertAfter>
That'll insert it after the gunCrossbow.

 
Should add a note about that 'exportcurrentconfigs' command to the OP's to help debug issues people may be having.

 
Have my new weapon ready to go, just no icon showing for it in game. Copied the template for the MR10.

The weapon shows up when you use it, just no icon.

I'd rather not extract the icon from the files, it's using the exact same one as the MR10.

Is there a way to just tack that in, or do I have to do the extract?

nvm, custom icon command, told it just to use the MR10 and it's fixed.

 
Last edited by a moderator:
That happens because the animalBear probably appears before the animalTemplateFriendly.
Instead of an append, which puts your animalTemplateFriendly at the bottom of the entityclasses.xml, try an insertBefore

Code:
<insertBefore xpath="/entity_classes/entity_class[@name='animalBear']" >
    <entity_class name="animalTemplateFriendly" >
               <!-- snip -->
   </entity_class>
</insertBefore>
Thanks shpereii, that worked! I should have realized that there was a reason more than readability that templates appeared before the entities using them! :D

 
Should add a note about that 'exportcurrentconfigs' command to the OP's to help debug issues people may be having.
What does that do, does it output a more verbose log of the parsing of the xpath entries?

7 Days To Die/7DaysToDie_Data contains output logs at least which are more verbose for general logging, but don't seem to be more verbose for xpath issues specifically in comparison to what the console already tells you.

 
What does that do, does it output a more verbose log of the parsing of the xpath entries?
7 Days To Die/7DaysToDie_Data contains output logs at least which are more verbose for general logging, but don't seem to be more verbose for xpath issues specifically in comparison to what the console already tells you.
Xpath gets applied when the game and worlds load. Seeing what the final XML looks like can help figure out when things don't go right. However, it'll only be useful if your changes were not fatal to the XML parsing.

 
Back
Top