• 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:
Code:
<insertAfter xpath="/lootcontainers/lootgroup[@name='garbage']">
<item group="otherJunk" count="1,3" prob="0.80"/>
<item group="metalJunk" count="1,3" prob="1.0"/>
</insertAfter>
looks like it would load the game without any errors.

but i checked 0ver 100 container and didn't get a single item from my both Container (otherJunk / metalJunk) .....

 
Code:
<insertAfter xpath="/lootcontainers/lootgroup[@name='garbage']">
<item group="otherJunk" count="1,3" prob="0.80"/>
<item group="metalJunk" count="1,3" prob="1.0"/>
</insertAfter>
looks like it would load the game without any errors.

but i checked 0ver 100 container and didn't get a single item from my both Container (otherJunk / metalJunk) .....
Do an exportcurrentconfigs, then look at the loot.xml in the path it provides you in the console (it's the save game folder), and see if your changes applied to the file.

 
my command:

Code:
<insertAfter xpath="/lootcontainers/lootgroup[@name='garbage']">
<item group="otherJunk" count="1,3" prob="0.80"/>
<item group="metalJunk" count="1,3" prob="1.0"/>
</insertAfter>
the config shows me the issue:

Code:
<lootgroup name="garbage">
<item group="junk" />
</lootgroup>
<item group="metalJunk" count="1,3" prob="1.0"><!--Element inserted by: "NewLifeExperience_Addon_MoreJunkItems"--></item>
<item group="otherJunk" count="1,3" prob="0.80"><!--Element inserted by: "NewLifeExperience_Addon_MoreJunkItems"--></item>
as you can see, my both lootgrous are out of reachable point^^ so this is a issue from the insertAfter command i think^^

could you help again to fix it :D ?

 
my command:
Code:
<insertAfter xpath="/lootcontainers/lootgroup[@name='garbage']">
<item group="otherJunk" count="1,3" prob="0.80"/>
<item group="metalJunk" count="1,3" prob="1.0"/>
</insertAfter>
the config shows me the issue:

Code:
<lootgroup name="garbage">
<item group="junk" />
</lootgroup>
<item group="metalJunk" count="1,3" prob="1.0"><!--Element inserted by: "NewLifeExperience_Addon_MoreJunkItems"--></item>
<item group="otherJunk" count="1,3" prob="0.80"><!--Element inserted by: "NewLifeExperience_Addon_MoreJunkItems"--></item>
as you can see, my both lootgrous are out of reachable point^^ so this is a issue from the insertAfter command i think^^

could you help again to fix it :D ?
Since it doesn't matter where it needs to exist, you can just use append :)

Code:
<append xpath="/lootcontainers/lootgroup[@name='garbage']">
       <item group="otherJunk" count="1,3" prob="0.80"/>
       <item group="metalJunk" count="1,3" prob="1.0"/>
</append>
 
Hi again :)

Thanks for trying to help :)

This is not working either. I thought about removing xpath... but didn't know i could use the 'wildcard forge category' in it because it is not mentioned there.

It's still only giving 1 - i also tried this:

Code:
<changedrecipes>


   <remove xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="1" /> </remove>


    <append xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="3" />
   </append>

</changerecipes>
and this

Code:
<changedrecipes>


   <remove xpath="/recipes/recipe[@name='resourceScrapLead']/wildcard_forge_category">
         <ingredient name="unit_lead" count="1" /> </remove>


    <append xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="3" />
   </append>

</changedrecipes>
still no luck. I tried your suggestion with and without the </remove> at the end.

greets cheeky2

 
Last edited by a moderator:
Hi again :)
Thanks for trying to help :)

This is not working either. I thought about removing xpath... but didn't know i could use the 'wildcard forge category' in it because it is not mentioned there.

It's still only giving 1 - i also tried this:

Code:
<changedrecipes>


   <remove xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="1" /> </remove>


    <append xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="3" />
   </append>

</changerecipes>
and this

Code:
<changedrecipes>


   <remove xpath="/recipes/recipe[@name='resourceScrapLead']/wildcard_forge_category">
         <ingredient name="unit_lead" count="1" /> </remove>


    <append xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="3" />
   </append>

</changedrecipes>
still no luck. I tried your suggestion with and without the </remove> at the end.

greets cheeky2
The remove is a single line command. Be sure to end it with />

You are telling xpath to remove the node called wildcard_forge_category

Code:
<remove xpath="/recipes/recipe[@name='resourceScrapLead']/wildcard_forge_category" />
 
Hi again :)

ok i didn't know that but when i try this (your suggestion from my first post)...

Code:
<changedrecipes>
   <remove xpath="/recipes/recipe[@name='resourceScrapLead']/wildcard_forge_category" />
   <append xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="3" />
   </append>
</changerecipes>
i get an error: Failed loading xml and parsing XML (recipes.xml)

XML exeption 'changed recipes' is expected Line 7 Position 10

so i tried some other codes which i could think of might work or not (in my second post)...

tried this now and get yet another error in Line 12 which is the Line where <changedrecipes> is written... :(

Code:
<changedrecipes>


   <remove xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="1" /> 


    <append xpath="/recipes/recipe[@name='resourceScrapLead']">
         <ingredient name="unit_lead" count="3" />
   </append>

</changerecipes>
omg i see it... changedrecipes and change(d)recipes... ok going to try again pff I just copied your code and didn't see that the d is missing lol

Still not working tho. I will try Malacay2k11's suggestion and see if that works.

thanks again for trying to help :)

greets cheeky2

 
Last edited by a moderator:
i can't use <append> to add my own LootContainer to "garbage"

cuz in den exportet Config, my own Containers are shown on the bottom of loot.xml

https://pastebin.com/cVLSGXps

error said wrong loading order...

so i need a way to place my own Container before gargabe....

 
@Cheeky2

amout of scrap_lead is appended on the material.xml and weight of the item...

every item with "Material" "Mlead" are scraped to Scrap_Lead. also the Forged merged these kind of Items into Scrap...

maybe you should just edit the weight of Lead items, to increase the Lead output !?

 
Can you only change things within the Config folder with Xpath? What about referencing the 'World' folder to alter things in there, is that possible?

 
Hi again :)

ok this works... thanks Malacay2k11 for the tip with the weight... it was in items.xml not in materials.xml btw.

Code:
<changedforgeoutput>

<append xpath="/items">
<item name="resourceScrapBrass"> <!-- scrap material -->
<property name="HoldType" value="45"/>
<property name="Meshfile" value="Items/Misc/sackPrefab"/>
<property name="DropMeshfile" value="Items/Misc/sack_droppedPrefab"/>
<property name="Material" value="MresourceScrapBrassSmall"/>
<property name="Stacknumber" value="6000"/> <!-- STK resource -->
<property name="Weight" value="3"/>                                                <<< changed this
<property name="EconomicValue" value="20"/>
<property name="EconomicBundleSize" value="10"/>
<property name="Group" value="Resources"/>
</item>

<item name="resourceScrapLead"> <!-- scrap material -->
<property name="HoldType" value="45"/>
<property name="Meshfile" value="Items/Misc/sackPrefab"/>
<property name="DropMeshfile" value="Items/Misc/sack_droppedPrefab"/>
<property name="Material" value="MresourceScrapLeadSmall"/>
<property name="Stacknumber" value="6000"/> <!-- STK resource -->
<property name="Weight" value="3"/>                                              <<< changed this
<property name="EconomicValue" value="20"/>
<property name="EconomicBundleSize" value="10"/>
<property name="Group" value="Resources"/>
</item>
</append>

</changedforgeoutput>
Thanks for all the help @sphereii and @ Malacay2k11 :)

greets cheeky2

 
i can't use <append> to add my own LootContainer to "garbage"cuz in den exportet Config, my own Containers are shown on the bottom of loot.xml

https://pastebin.com/cVLSGXps

error said wrong loading order...

so i need a way to place my own Container before gargabe....
Sorry, I may have misunderstood. Rather than insertAfter, try insertBefore. Same syntax.

- - - Updated - - -

Can you only change things within the Config folder with Xpath? What about referencing the 'World' folder to alter things in there, is that possible?
Correct, only the files under Config. We are hoping for more support in the future for prefab loading, etc.

 
Correct, only the files under Config. We are hoping for more support in the future for prefab loading, etc.
Thank you for the reply. I look forward to that development, I already have plans, :smile-new:

 
Thank you for the reply. I look forward to that development, I already have plans, :smile-new:
Same... distributing a custom prefab, with its custom blocks, entities, etc... would be a lot of fun, I think.

 
Can the set command replace an enitre node?

for example, if I were to change

Code:
<biome name="city">
<spawn maxcount="3" respawndelay="1" time="Day" entitygroup="ZombiesAll" />
<spawn maxcount="5" respawndelay="1" time="Night" entitygroup="ZombiesNight" />
<spawn maxcount="1" respawndelay="1" time="Any" entitygroup="ZombieDogGroup" />
</biome>
to

Code:
<biome name="city">
<spawn maxcount="10" respawndelay="0.25" time="Day" entitygroup="ZombiesAll" />
<spawn maxcount="6" respawndelay="0.5" time="Night" entitygroup="ZombiesNight" />
<spawn maxcount="1" respawndelay="0.5" time="Any" entitygroup="ZombieDogGroup" />
</biome>
could I do that in a single set command, and what would be the syntax if so?

 
Can the set command replace an enitre node?
for example, if I were to change

Code:
<biome name="city">
<spawn maxcount="3" respawndelay="1" time="Day" entitygroup="ZombiesAll" />
<spawn maxcount="5" respawndelay="1" time="Night" entitygroup="ZombiesNight" />
<spawn maxcount="1" respawndelay="1" time="Any" entitygroup="ZombieDogGroup" />
</biome>
to

Code:
<biome name="city">
<spawn maxcount="10" respawndelay="0.25" time="Day" entitygroup="ZombiesAll" />
<spawn maxcount="6" respawndelay="0.5" time="Night" entitygroup="ZombiesNight" />
<spawn maxcount="1" respawndelay="0.5" time="Any" entitygroup="ZombieDogGroup" />
</biome>
could I do that in a single set command, and what would be the syntax if so?
No, this would be multiple sets for each attribute you wanted to change. Alternatively, you could just remove the biome[@name=city] and append a new one.

 
Is it considered bad practice to overwrite an entire XML file?
for a shareable modlet, yes. You won't know what changes were done previously.

If you were just doing an Overhaul, it'd be fine.

 
Back
Top